目录

一、实验目的

二、实验任务

三、实验原理

1  LL(1)文法

2  LR文法

四、实验过程

1  LL(1)文法

2  LR文法

五、实验结果

1  LL(1)文法

2  LR(0)文法

3  LR(1)文法

参考资料

附录

1 LL(1)代码

2 LR(0)文法

3  LR(1)代码


一、实验目的

1、掌握非递归下降的预测分析;

2、了解如何使用Yacc、bision等工具完成语法分析

二、实验任务

1、针对书上第三章中的表达式文法,采用LL(1)、LR(1)进行分析(必做),不需要做词法分析,输入为记号流。可以手工构造预测分析表,但鼓励自动生成。

2、使用Yacc或bision等工具,实现对表达式文法的语法分析析(附加)。

三、实验原理

1  LL(1)文法

任何两个产生式A ®a | b 都满足下列条件:

(1)FIRST(a ) Ç FIRST(b ) = Æ;

(2)若b Þ* e ,那么FIRST(a) Ç FOLLOW(A) = Æ。

把满足这两个条件的文法称为LL(1)文法。先定义两个和文法有关的函数FIRST(a ) = {a | a Þ* a…, a Î VT},特别是,a Þ* e时,规定e Î FIRST(a ) ;FOLLOW(A) = {a | S Þ* …Aa…,aÎVT},如果A是某个句型的最右符号,那么$属于FOLLOW(A)。

  1. 查找非终结符的First

Step 1:按产生式顺序来,从开始符找起;

Step 2:如果右部的串首为终结符,则直接将该终结符填入左部非终结符的First集中;

Step 3:如果右部的串首为非终结符,则左部非终结符的First集等价于串首非终结符的First集。因而,需要利用Step 2和Step 3继续寻找串首非终结符的First集。

  1. 查找非终结符的Follow

Step 1:按产生式顺序来,从开始符找起(开始符的Follow集必定包含$);

Step 2:从所有产生式右部寻找目标非终结符,若其后紧跟终结符,则将终结符填入目标非终结符的Follow集。特别地,若其后紧跟$,则目标非终结符的Follow集等价于产生式左部非终结符的Follow集。

Step 3:从所有产生式右部寻找目标非终结符,若其后紧跟非终结符,则将该非终结符的First集元素填入目标非终结符的Follow集。特别地,若该非终结符的First集元素中包含e,则需针对e情况时做特殊处理,即目标非终结符的Follow集等价于产生式左部非终结符的Follow集。

LL(1)文法有一些明显的性质:没有公共左因子;不是二义的;不含左递归。

  1. 构造预测分析表

(1)对文法的每个产生式A ® a ,执行(2)和(3);

(2)对FIRST(a)的每个终结符a,把A ® a 加入M[A, a];

(3)如果e在FIRST(a)中,对FOLLOW(A)的每个终结符b(包括$),把A ® a加入M[A, b];

(4)M中其它没有定义的条目都是error。

2  LR文法

LR分析器的模型如图所示,它包括输入、输出、栈、驱动程序和含动作和转移两部分的分析表。驱动程序对所有的LR分析方法都一样,不同的分析方法构造的分析表不同。分析程序每次从输入缓冲区读一个符号,它使用栈存储形式为s0X1s1X2s2⋯Xmsm 的串,sm 在栈顶。Xi 是文法符号,si是叫做状态的符号,状态符号概括了栈中它下面部分所含的信息。栈顶的状态符号和当前的输入符号用来检索分析表,以决定移进—归约分析的动作。

图 3.1:LR分析器的模型

2.1  LR(0)文法

文法G的LR(0)项目(简称项目)是在右部的某个地方加点的产生式。如产生式A→XYZ对应有四个项目:

A→·XYZ

A→X·YZ

A→XY·Z

A→XYZ·

产生式A→ε只有一个项目A→·和它对应。直观地讲,项目表示在分析过程的某一点,已经看见了产生式的多大部分(点的左边部分)和下面希望看见的部分。

2.2  LR(1)文法

让状态含有更多的信息,使之能够剔除无效归约是完全可能的。定义项目,使之包含一个终结符作为第二个成分,这样就把更多的信息并入了状态。项目的一般形式也就成了[A→α·β,a],其中A→αβ是产生式,a是终结符号或$,这种项目叫做LR(1)项目,1是第二个成分的长度,这个成分叫做项目的搜索符。搜索符对β非空的项目[A→α·β,a]是不起作用的,但对形式为[A→α·,a]的项目,它表示只有在下一个输入符号是a时,才能要求按A→α归约。这样,分析器只有在输入符号是a时才按A→α归约,其中[A→α·,a]在栈顶状态的LR(1)项目集中。这样的a的集合是FOLLOW(A)的子集,完全可能是真子集。我们说LR(1)项目[A→α·β,a]对活前缀γ是有效的,如果存在着推导S=>*rmδAw=>rmδαβw,其中:

(1)  γ=δα

(2) a是w的第一个符号,或者w 是ε且a是$。

在LR(1)文法中,栈中的文法符号总是形成一个活前缀,分析表的转移函数本质上是识别活前缀的DFA,栈顶的状态符号包含了确定句柄所需要的一切信息,是已知的最一般的无回溯的移进归约方法,能及时发现语法错误,但是,手工构造分析表的工作量太大。

LR分析法的规约过程是规范推倒的逆过程,所以LR分析过程是一种规范规约的逆过程,L表示从左到右扫描输入串, R表示最左规约(即最右推导的逆过程),括号中的1表示向右查看输入符号数为1。LR(1)项目可以看成两个部分组成,一部分和LR(0)项目相同,这部分成为心,另一部分为向前搜索符集合。所以只有当面临的输入符属于向前搜索符的集合,才做规约动作,其他情况均出错。LR(1)方法恰好解决LR(0)(1)方法在某些情况下存在的无效规约问题。

四、实验过程

1  LL(1)文法

LL(1)文法的分析模型如图4.1所示,课本上要分析的文法(3.8)如下:

E→TE′

E′→+TE′|ε

T→FT′

T′→*FT′|ε

F→(E)|id

图4.1:LL(1)文法的分析模型

(1)构造LL(1)预测分析表,按照实验原理中描述的流程,最终分析表如下表所示。

表4.1:LL(1)预测分析表

在实际编程中,用字典进行存储,其中P代表E′,p代表T′,e代表e,如下所示:

#Epie=P;Tpie=p;yimuxitong=e

dicM={

"E":{"i":"TP","C":"TP"},

"P":{"+":"+TP",")":"e","$":"e"},

"T":{"i":"Fp","(":"Fp"},

"p":{"+":"e","*":"*Fp",")":"e","$":"e"},

"F":{"i":"i","(":"(E)"}

}

(2)按照LL(1)文法分析的伪代码进行编程,具体代码详见附录1.

图4.2:LL(1)文法的伪代码

2  LR文法

LR(1)文法的分析模型如图3.1所示.

2.1  LR(0)文法

利用LR(0)课本上要分析的文法(3.11)如下:

E->E+T

E->T

T->T*F

T->F

F->(E)

F->i

(1)构造LR(0)预测分析表,按照实验原理中描述的流程,最终分析表如下表所示。

表4.2:LR(0)预测分析表

在实际编程中,用字典进行存储,如下所示:

action={0: {'i': 's5', '(': 's4'},

1: {'+': 's6', '$': 'acc'},

2: {'+': 'r2', '*': 's7', ')': 'r2', '$': 'r2'},

3: {'+': 'r4', '*': 'r4', ')': 'r4', '$': 'r4'},

4: {'i': 's5', '(': 's4'},

5: {'+': 'r6', '*': 'r6', ')': 'r6', '$': 'r6'},

6: {'i': 's5', '(': 's4'},

7: {'i': 's5', '(': 's4'},

8: {'+': 's6', ')': 's11'},

9: {'+': 'r1', '*': 's7', ')': 'r1', '$': 'r1'},

10: {'+': 'r3', '*': 'r3', ')': 'r3', '$': 'r3'},

11: {'+': 'r5', '*': 'r5', ')': 'r5', '$': 'r5'}}

goto={0: {'E': 1, 'T': 2, 'F': 3},

4: {'E': 8, 'T': 2, 'F': 3},

6: {'T': 9, 'F': 3},

7: {'F': 10}}

(2)按照LR(0)文法分析的伪代码进行编程,具体代码详见附录2.

图4.3:LR(0)文法的伪代码

2.2  LR(1)文法

课本上要分析的文法(3.13)如下:

对下列文法,用LR(1)分析法对任意输入的符号串进行分析:

E->S

S->BB

B->bB|a

程序的流程图如图所示,其中输入以#结束的符号串(包括a、b、#),如:abb#。此文法采用C++进行编程,对应文法分析表Action的存储结构为字符型二维数组,Goto的存储结构为整数型二维数组,如下所示:

图4.4: LR(1)分析流程图

图4.5:LR(1)分析表的存储结构示意图

五、实验结果

1  LL(1)文法

程序识别出文法的非终结符VN集合为:['E', 'P', 'T', 'p', 'F'];终结符VT集合为['(', 'C', '+', ')', '*', 'i', '$', 'e'],其中P代表E′,p代表T′,e代表e。输入符号串i*i+i,分析结果如下图所示,经过17步分析,最终判断该句子属于该文法,分析结束。当然,如果输入i*+i,不符合该文法的句子,结果如图5.2所示,最终判断该句子不属于该文法。说明程序编写正确。

图5.1: 句子“i*i+i”的LL(1)分析过程

图5.2: 句子“i*+i”的LL(1)分析过程

2  LR(0)文法

输入句子“i*i+i$”,采用LR(0)文法进行分析的结果如下,经过14步分析,最终判断该句子属于该文法,分析结束;当然,如果输入i*+i,不符合该文法的句子,结果如图5.4所示,最终判断该句子不属于该文法。程序编写正确。

图5.3: 句子“i*i+i”的LR(0)分析过程

图5.4: 句子“i*+i”的LR(0)分析过程

3  LR(1)文法

输入句子“abb#”,采用LR(1)文法进行分析的结果如下,经过8步分析,最终判断该句子属于该文法,分析结束;输入句子“abbab#”,采用LR(1)文法进行分析的结果如下,经过6步分析,最终判断该句子不属于该文法,分析结束。

图5.5:LR(1)文法的分析过程

参考资料

  1. 自上而下语法分析器python:https://blog.csdn.net/zhengjue3343/article/details/80042782
  2. 基于LR(1)的语法检查器(一):https://blog.csdn.net/Maxners/article/details/78974766
  3. LR(1)文法实现:python | 编译原理,语法分析——LR(1)文法实现_int_Brosea的博客-CSDN博客_lr(1)文法
  4. LR(1)文法:https://wenku.baidu.com/view/556116976bec0975f465e223.html

附录

1 LL(1)代码

# -*- coding: utf-8 -*-

"""

Created on Thu Apr 16 10:41:01 2020

@author: 小果果学长

"""

#分析表M

#dicM={

#    "S":{"(":"A", ")":"A"},

#    "A":{"(":"CB", ")":"CB" },

#    "B":{"i":"iCB","*":"e", "$":"e"},

#    "C":{"(":"ED", ")":"ED" },

#    "D":{"i":"e","+":"+ED","*":"e", "$":"e"},

#    "E":{"(":"(", ")":")A*" }

#}

#Epie=P;Tpie=p;yimuxitong=e

dicM={

"E":{"i":"TP","C":"TP"},

"P":{"+":"+TP",")":"e","$":"e"},

"T":{"i":"Fp","(":"Fp"},

"p":{"+":"e","*":"*Fp",")":"e","$":"e"},

"F":{"i":"i","(":"(E)"}

}

#非终结符

VN=[]

for item in dicM.keys():

VN.append(item);

print("非终结符VN集合为:{0}".format(VN))

#终结符

VT=[]

# print(len(dicM))

for item in dicM.values():

for it in item:#遍历key值

VT.append(it)

VT=list(set(VT))

VT.append("e")

print("终结符VT集合为{0}:".format(VT))

#翻转字符串,返回字符串

def convertStr(arg):

conarg=arg[::-1]

return conarg

#找产生式,返回产生式右部

def findCSS(argS,argstr):

if argS in dicM.keys() :

temp_value=dicM[argS]

if argstr in temp_value.keys():

temp=temp_value[argstr]

return temp

return ""

#截取列表 除去最后一个元素

def substr(arg):

# print(arg,"fdsfs")

Listarg=list(arg)

le=len(Listarg)

args=Listarg[0:le-1]

return args

def addS(arg,args):

Listargs=list(args)

for i in arg:

Listargs.append(i)

return  Listargs

#strString=input("请输入要分析的符号串:")#输入串

strString="i*i+i"

str=list(strString)

str.append("$")

COUNT=0#步骤

#符号栈

S=["$"]

S.append(VN[0])

# print(S)

CSRight=""

print("步骤\t符号栈S[i]\t\t\t输入串str[j]\t\t\t产生式")

while len(S)!=0:

COUNT += 1

ch = str[0]

CSRight0 = findCSS(S[-1], str[0])

if CSRight0!="" and S[-1] not in VT:

print("%s\t%s\t\t\t\t%s\t\t\t\t%s" % ( COUNT, "".join(S).center(10), "".join(str).center(10),S[-1] + "->" +CSRight0))

elif  CSRight0 in VT or S[-1]  in VT:

print("%s\t%s\t\t\t\t%s" % ( COUNT, "".join(S).center(10), "".join(str).center(10)))

elif CSRight0=="":

print("\033[0;31m%s\033[0m" % "该句子不是该文法!")

break

CHS = S.pop()

CSRight = findCSS(CHS, str[0])

if CHS not in VT  :#如果栈顶元素不是终结字符

if CSRight!="":

if CSRight[0] in VN :

temp = convertStr(CSRight)

S = addS(temp,S)

elif CSRight[0] in VT and CSRight[0]!="e":

temp = convertStr(CSRight)

S = addS(temp, S)

elif CSRight[0]=="e" and CSRight[0] in VT:

pass

elif CSRight=="":

pass

elif CHS in VT:

if ch==CHS:

if CHS=="$":

# print("该句子属于该文法!")

print("\033[1;31;40m该句子属于该文法!\033[0m")

elif CHS!="$":

str = str[1:]

elif ch!=CHS:

if CHS=="$":

print("\033[0;31m%s\033[0m" % "该句子不是该文法!")

pass

2 LR(0)文法

2.1 LR(0)代码

#使用已经建立好的分析表

action={0: {'i': 's5', '(': 's4'},

1: {'+': 's6', '$': 'acc'},

2: {'+': 'r2', '*': 's7', ')': 'r2', '$': 'r2'},

3: {'+': 'r4', '*': 'r4', ')': 'r4', '$': 'r4'},

4: {'i': 's5', '(': 's4'},

5: {'+': 'r6', '*': 'r6', ')': 'r6', '$': 'r6'},

6: {'i': 's5', '(': 's4'},

7: {'i': 's5', '(': 's4'},

8: {'+': 's6', ')': 's11'},

9: {'+': 'r1', '*': 's7', ')': 'r1', '$': 'r1'},

10: {'+': 'r3', '*': 'r3', ')': 'r3', '$': 'r3'},

11: {'+': 'r5', '*': 'r5', ')': 'r5', '$': 'r5'}}

goto={0: {'E': 1, 'T': 2, 'F': 3},

4: {'E': 8, 'T': 2, 'F': 3},

6: {'T': 9, 'F': 3},

7: {'F': 10}}

gramma=open('wx.txt').readlines()

i=0

while i<len(gramma): #去掉'->'符号

gramma[i]=gramma[i][0:1]+gramma[i][3:len(gramma[i])-1]

i+=1

#sen='i*i+i$'

sen='i*+i$'

ip=0#sen的指针

stack=['$',0]

a=sen[ip]

while True:

print(stack, end="")

print("\t",end="")

s=stack[len(stack)-1] #s为栈顶状态

if  a in action[s]:#存在action[s][a]

if action[s][a]=='acc': #若为acc 则成功,并结束

print("\033[1;31;40mAccept,该句子属于该文法!\033[0m")

break

elif action[s][a][0]=='s':#若为 si 则把a和i依次入栈 a指向下一个

print('移进'+action[s][a])

t=int(action[s][a][1])

stack.append(a)

stack.append(t)

ip+=1

a=sen[ip]

elif action[s][a][0]=='r':#若为ri i为第i个文法(gramma[i-1]) 则栈回退2*gramma[i-1]表达式表达式右端的长度

print('规约'+gramma[int(action[s][a][1])-1][0:1]+'->'+gramma[int(action[s][a][1])-1][1:])

size=len(gramma[int(action[s][a][1])-1])-1 #rj 对应的第j个产生式右端的长度

j=0

while j<2*size:

stack.pop()

j+=1

t=stack[len(stack)-1]#t为现在栈的状态

stack.append(gramma[int(action[s][a][1])-1][0])#表达式左端入栈

stack.append(goto[t][gramma[int(action[s][a][1])-1][0]])#goto[t,表达式左端]入栈

else:

#调用错误恢复例程

print('error')

break;

2.2 wx.txt附件

*注:最后一行有换行。

E->E+T

E->T

T->T*F

T->F

F->(E)

F->i

3  LR(1)代码

#include<stdio.h>

#include<string.h>

char *action[10][3]= {"S3#","S4#",NULL,           /*ACTION表*/

NULL,NULL,"acc",

"S6#","S7#",NULL,

"S3#","S4#",NULL,

"r3#","r3#",NULL,

NULL,NULL,"r1#",

"S6#","S7#",NULL,

NULL,NULL,"r3#",

"r2#","r2#",NULL,

NULL,NULL,"r2#"

};

int goto1[10][2]= {1,2,                                               /*QOTO表*/

0,0,

0,5,

0,8,

0,0,

0,0,

0,9,

0,0,

0,0,

0,0

};

char vt[3]= {'a','b','#'};                       /*存放非终结符*/

char vn[2]= {'S','B'};                           /*存放终结符*/

char *LR[4]= {"E->S#","S->BB#","B->bB#","B->a#"};/*存放产生式*/

int a[10];

char b[10],c[10],c1;

int top1,top2,top3,top,m,n;

int main()

{

int g,h,i,j,k,l,p,y,z,count;

char x,copy[10],copy1[10];

top1=0;

top2=0;

top3=0;

top=0;

a[0]=0;

y=a[0];

b[0]='#';

count=0;

z=0;

printf("请输入表达式\n");//abb#

do {

scanf("%c",&c1);

c[top3]=c1;

top3=top3+1;

} while(c1!='#');

printf("步骤\t状态栈\t\t符号栈\t\t输入串\t\tACTION\tGOTO\n");

do {

y=z;

m=0;

n=0;                      /*y,z指向状态栈栈顶*/

g=top;

j=0;

k=0;

x=c[top];

count++;

printf("%d\t",count);

while(m<=top1) {

/*输出状态栈*/

printf("%d",a[m]);

m=m+1;

}

printf("\t\t");

while(n<=top2) {

/*输出符号栈*/

printf("%c",b[n]);

n=n+1;

}

printf("\t\t");

while(g<=top3) {

/*输出输入串*/

printf("%c",c[g]);

g=g+1;

}

printf("\t\t");

while(x!=vt[j]&&j<=2) j++;

if(j==2&&x!=vt[j]) {

printf("error\n");

return 0;

}

if(action[y][j]==NULL) {

printf("error\n");

return 0;

}   else    strcpy(copy,action[y][j]);

if(copy[0]=='S') {

/*处理移进*/    z=copy[1]-'0';

top1=top1+1;

top2=top2+1;

a[top1]=z;

b[top2]=x;

top=top+1;

i=0;

while(copy[i]!='#') {

printf("%c",copy[i]);

i++;

}

printf("\n");

}

if(copy[0]=='r') {

/*处理归约*/    i=0;

while(copy[i]!='#') {

printf("%c",copy[i]);

i++;

}

h=copy[1]-'0';

strcpy(copy1,LR[h]);

while(copy1[0]!=vn[k]) k++;

l=strlen(LR[h])-4;

top1=top1-l+1;

top2=top2-l+1;

y=a[top1-1];

p=goto1[y][k];

a[top1]=p;

b[top2]=copy1[0];

z=p;

printf("\t");

printf("%d\n",p);

}

} while(action[y][j]!="acc");

printf("恭喜你,分析成功!\n");

return 0;

}

【编译原理】Python语法分析LL(1)、LR(1)相关推荐

  1. 编译原理实验(三)——LR(0)语法分析

    编译原理实验(三)--LR(0)语法分析 实验要求 参考程序 实验结果 程序输入说明 截图 实验要求 根据LR(0)分析法编写一个语法分析程序 直接输入根据已知文法构造的分析表M;对于输入的文法和符号 ...

  2. lr1分析器c语言实验报告怎么写,编译原理课程的设计构造LR分析法语法分析器.doc...

    编译原理课程的设计构造LR分析法语法分析器 太 原 学 院 课程设计报告书 课程名称 设计题目 构造LR(0)分析法语法分析器 专业班级 学 号 姓 名 指导教师 2016年 12 月 15日 目 录 ...

  3. 编译原理之LL(1) 、LR(0)、SLR、LR(1)、LALR文法的对比

    原创 编译原理之LL(1) .LR(0).SLR.LR(1).LALR文法的对比 2018-01-12 21:42:09 棉花糖灬 阅读数 25323 收起 分类专栏: 那些有趣的知识 版权声明:本文 ...

  4. 编译原理,C语言实现LR(0)分析(扩展文法的生成、项目集规范簇的生成、ACTION GOTO表的生成、句子的分析)

    编译原理,C语言实现LR0分析扩展文法的生成.项目集规范簇的生成.ACTION GOTO表的生成.句子的分析 演示 演示所用文法和句子 (1)根据提示输入文法的个数 (2)输入文法 (3)扩展文法的生 ...

  5. 编译原理之语法分析(自底向上)(包含源码)

    编译器之语法分析 自底向上 基本概念 算符优先 SLR 规范LR LALR 自底向上 基本概念 自底向上形成语法树的过程就是及逆行归约,将一堆单词串放在一起,形成某个产生式的样子,然后规约成某个产生式 ...

  6. 编译原理2-Bison语法分析

    ps:补上了图 实验要求 了解 Bison 基础知识和理解 Cminus-f 语法(重在了解如何将⽂法产⽣式转换为 Bison 语句) 阅读 /src/common/SyntaxTree.c ,对应头 ...

  7. 编译原理之语法分析(预测分析法)

    编译器之语法分析 自顶向下 上下文无关文法 语法树 NFA→CFG 预测分析法 改写CFG 原因 消除二义性 消除左递归 消除左公因子 消除空产生式 消除回路 自顶向下 上下文无关文法 CFG本质上就 ...

  8. 编译原理——自上而下语法分析

    自上而下分析面临的问题 回溯 (当候选有多个的时候,匹配失败会造成回溯) 文法左递归问题 那么他这个语法树就会无限增长但是分析并没有继续进行下去,就会导致分析进入死循环中 LL1文法消除左递归 消除直 ...

  9. 编译原理词/语法分析

    效果: 代码: 1: using System; 2: using System.Collections.Generic; 3: using System.ComponentModel; 4: usi ...

  10. 计算机语法分析,电子科技大学-计算机学院-编译原理实验-语法分析.pdf

    // SyntaxAnalyzer.cpp : 定义控制台应用程序的入口点. // #include #include #include #define MAX_COUNT 1024 #define ...

最新文章

  1. 理解JSON对象:JSON.parse、 JSON.stringify
  2. The Web Audio autoplay policy will be re-enabled in 音频无法播放
  3. 联发科mtk和骁龙730哪个好_不惧高通挑战!联发科G90芯片发布,强势干翻骁龙730...
  4. 部署Windows Server Update Services 4.0
  5. 一位网络工程师的终告
  6. java mdpi_如何使用drawable兼容所有屏幕尺寸(idpi,mdpi,hdpi,xhdpi,xxhdpi)
  7. Web 端 js 导出csv文件(使用a标签)
  8. 5G:无人驾驶的“超级英雄”路
  9. [备忘]windows下安装PHP环境php.ini-recommended 跟php.ini-dist 的差别之处
  10. 下载LineageOS 源码编译
  11. Python3连接SSH服务器并下载日志文件
  12. 使用C++编写一个DHT爬虫,实现从DHT网络爬取BT种子
  13. 前端实现——html2pdf功能(完成)
  14. 域名注册及免费空间and企业邮箱
  15. 微信公众号html在线编辑器,【微信公众平台工具开发】雷人微信网页编辑器
  16. 2D草图实时3D建模,可跑可跳无需手动绑定骨骼丨开源
  17. video视频播放过程抓取图片/截图并在浏览器端下载
  18. 7-20 表达式转换 (25 分)
  19. 【genius_platform软件平台开发】第九十四讲:int64_t的格式化问题(lld和PRId64)
  20. JSP实现养老院管理系统

热门文章

  1. C语言探索之旅 | 第一部分第三课:你的第一个程序
  2. Altium designer18系列教程一 建工程和封装介绍
  3. Greenplum实战-gpstop gpstart集群命令
  4. emc整改措施及案例_EMC整改经典对策
  5. centos7下mysql忘记密码并修改
  6. 计算机专业欧美排名,数字媒体艺术大学排名TOP3世界榜一览!
  7. 墨客开发者行动(上海站)
  8. tiny core linux网络连接,用Tiny Core Linux打造纯Firefox上网系统(概要)
  9. html怎样导入ps,【Photoshop软件新手向】如何导入/自制笔刷?
  10. 企业如何远程招聘到靠谱的程序员?--Codassium网页视频聊天工具