使用了
上一篇文章的方法,我已经用C#把
NativeX语言的语法分析器写出来了。而且最近把代码文件重构了一遍,删除掉了原来的实验性工程,转而重新设计了一个比较合理的工程结构,当然还是提交到了
Vczh Library++ 3.0的页面上去了。现在先来看一看给IDE使用的文法哈。现在语法分析器已经有两套了,一套是C++写的用于开发NativeX的编译器的,另一套是C#写的用于开发NativeX的IDE的。用来写编译器的文法在严格的同时还要指定错误信息的产生过程,而用于IDE的语法分析器就比较宽松一点了。
首先是C++版本的:
1 linking = (ALIAS >> (ID + (DOT >> ID))[ToLinking]);
2
3 primitive = TRUE[ToTrue] | FALSE[ToFalse]
4 | ACHAR[ToAChar] | WCHAR[ToWChar]
5 | ASTRING[ToAString] | WSTRING[ToWString]
6 | FLOAT[ToFloat] | DOUBLE[ToDouble]
7 | NULL_VALUE[ToNull]
8 | EXCEPTION_VALUE[ToException]
9 | INTEGER[ToInteger]
10 ;
11
12 reference = (ID + (LT(NeedLt) >> type(NeedTypeExpression) << GT(NeedGt)) + (COLON(NeedColon) + COLON(NeedColon) >> ID(NeedID)))[ToBasicInstanceFunctionExpression]
13 | (ID + (LT(NeedLt) + list(opt(type + *(COMMA >> type))) << GT(NeedGt)))[ToInstanciatedExpression]
14 | ID[ToReference]
15 ;
16
17 exp0 = primitive(NeedExpression)
18 | reference
19 | RESULT[ToResult]
20 | (CAST + (LT(NeedLt) >> type << GT(NeedGt)) + (OPEN_BRACE(NeedOpenBrace) >> exp << CLOSE_BRACE(NeedCloseBrace)))[ToCastExpression]
21 | (OPEN_BRACE >> exp << CLOSE_BRACE(NeedCloseBrace))
22 ;
23
24 exp1 = lrec(exp0 + *(
25 (OPEN_ARRAY + exp << CLOSE_ARRAY(NeedCloseArray))
26 | (OPEN_BRACE + list(opt(exp + *(COMMA >> exp)))[UpgradeArguments] << CLOSE_BRACE(NeedCloseBrace))
27 | ((DOT | POINTER) + ID[ToReference])
28 | ((INCREASE | DECREASE)[UpgradePostfix])
29 ), ToPostUnary);
30 exp2 = exp1 | ((INCREASE | DECREASE | BIT_AND | MUL | SUB | BIT_NOT | NOT) + exp2)[ToPreUnary];
31 exp3 = lrec(exp2 + *((MUL | DIV | MOD) + exp2), ToBinary);
32 exp4 = lrec(exp3 + *((ADD | SUB) + exp3), ToBinary);
33 exp5 = lrec(exp4 + *((LT+LT | GT+GT) + exp4), ToBinary2);
34 exp6 = lrec(exp5 + *((LT | GT | LE | GE) + exp5), ToBinary);
35 exp7 = lrec(exp6 + *((EQ | NE) + exp6), ToBinary);
36 exp8 = lrec(exp7 + *(BIT_AND + exp7), ToBinary);
37 exp9 = lrec(exp8 + *(XOR + exp8), ToBinary);
38 exp10 = lrec(exp9 + *(BIT_OR + exp9), ToBinary);
39 exp11 = lrec(exp10 + *(AND + exp10), ToBinary);
40 exp12 = lrec(exp11 + *(OR + exp11), ToBinary);
41 exp = lrec(exp12 + *((OP_ASSIGN | ASSIGN) + exp12), ToBinary);
42
43 functionType = (FUNCTION(NeedType) + type + (OPEN_BRACE(NeedOpenBrace) >> list(opt(type + *(COMMA >> type))) << CLOSE_BRACE(NeedCloseBrace)))[ToFunctionType];
44 primType = functionType
45 | ((PRIM_TYPE | ID)[ToNamedType] + (LT(NeedLt) + list(opt(type + *(COMMA >> type))) << GT(NeedGt)))[ToInstanciatedGenericType]
46 | (PRIM_TYPE | ID)[ToNamedType]
47 ;
48
49 type = lrec(primType + *(MUL | (OPEN_ARRAY >> INTEGER << CLOSE_ARRAY)), ToDecoratedType);
50
51 statement = SEMICOLON(NeedStatement)[ToEmptyStat]
52 | (exp + SEMICOLON(NeedSemicolon))[ToExprStat]
53 | (VARIABLE + type + ID(NeedID) + opt(ASSIGN >> exp) << SEMICOLON(NeedSemicolon))[ToVarStat]
54 | (IF + (OPEN_BRACE(NeedOpenBrace) >> exp << CLOSE_BRACE(NeedCloseBrace)) + statement + opt(ELSE >> statement))[ToIfStat]
55 | (BREAK << SEMICOLON(NeedSemicolon))[ToBreakStat]
56 | (CONTINUE << SEMICOLON(NeedSemicolon))[ToContinueStat]
57 | (EXIT << SEMICOLON(NeedSemicolon))[ToReturnStat]
58 | (OPEN_STAT + list(*statement) << CLOSE_STAT(NeedCloseStat))[ToCompositeStat]
59 | (DO + statement + (WHILE(NeedWhile) >> OPEN_BRACE(NeedOpenBrace) >> exp << CLOSE_BRACE(NeedCloseBrace) << SEMICOLON(NeedSemicolon)))[ToDoWhileStat]
60 | (LOOP + statement)[ToLoopStat]
61 | (WHILE + (OPEN_BRACE(NeedOpenBrace) >> exp << CLOSE_BRACE(NeedCloseBrace)) + statement + opt(WHEN >> OPEN_BRACE(NeedOpenBrace) >> exp << CLOSE_BRACE(NeedCloseBrace) << SEMICOLON(NeedSemicolon)))[ToWhileStat]
62 | (FOR + list(*statement) + (WHEN(NeedWhen) >> OPEN_BRACE(NeedOpenBrace) >> exp << CLOSE_BRACE(NeedCloseBrace)) + (WITH(NeedWith) >> list(*statement)) + (DO(NeedDo) >> statement))[ToForStat]
63 | (TRY + (statement + (CATCH(NeedCatch) >> statement)))[ToTryCatch]
64 | (THROW + opt(exp) << SEMICOLON(NeedSemicolon))[ToThrow]
65 ;
66
67 instanceType = (PRIM_TYPE | ID)[ToNamedType]
68 ;
69
70 functionDeclaration
71 = (FUNCTION + type + ID(NeedID) + (OPEN_BRACE(NeedOpenBrace) >> plist(opt((type + ID(NeedID)) + *(COMMA >> (type + ID(NeedID))))) << CLOSE_BRACE(NeedCloseBrace)) + opt(linking << SEMICOLON(NeedSemicolon)) + opt(statement))[ToFuncDecl]
72 ;
73
74 nonGenericDeclaration
75 = (VARIABLE + type + ID(NeedID) + opt(linking) + opt(ASSIGN >> exp) << SEMICOLON(NeedSemicolon))[ToVarDecl]
76 | (TYPE + ID + (ASSIGN(NeedAssign) >> type) << SEMICOLON(NeedSemicolon))[ToTypedefDecl]
77 | (STRUCTURE + ID(NeedID) << SEMICOLON(NeedSemicolon))[ToStructPreDecl]
78 | (STRUCTURE + ID(NeedID) + opt(linking) + (OPEN_STAT(NeedOpenStruct) >> *(type + ID(NeedID) << SEMICOLON(NeedSemicolon)) << CLOSE_STAT(NeedCloseStruct)))[ToStructDecl]
79 | (INSTANCE >> (instanceType + (COLON(NeedColon) >> ID << SEMICOLON(NeedSemicolon))))[ToInstancePreDecl]
80 | ((INSTANCE >> (instanceType + (COLON(NeedColon) >> ID)))+(OPEN_STAT(NeedOpenConcept)>>*((ID(NeedID)+(ASSIGN(NeedAssign)>>reference)<<SEMICOLON(NeedSemicolon)))[ToFunctionInstance]<<CLOSE_STAT(NeedCloseConcept)))[ToInstanceDecl]
81 | functionDeclaration
82 | (FOREIGN >> functionDeclaration)[ToForeignFunctionDecl]
83 ;
84
85 Node<TokenInput<RegexToken>, ParsingList<RegexToken>> genericHead
86 = (GENERIC>>LT(NeedLt)>>plist(ID(NeedID)+*(COMMA>>ID(NeedID)))<<GT(NeedGt))
87 ;
88 Node<TokenInput<RegexToken>, ParsingPair<RegexToken, RegexToken>> genericConstraintClause
89 = ID(NeedID) + (COLON(NeedColon) >> ID(NeedID))
90 ;
91 Node<TokenInput<RegexToken>, ParsingList<ParsingPair<RegexToken, RegexToken>>> genericConstraint
92 = WHERE >> (plist(genericConstraintClause + *(COMMA >> genericConstraintClause)))
93 ;
94 declaration = nonGenericDeclaration
95 | (CONCEPT>>ID(NeedID)+(COLON(NeedColon)>>ID(NeedID))+opt(linking)+(OPEN_STAT(NeedOpenConcept)>>*((ID(NeedID)+(ASSIGN(NeedAssign)>>functionType)<<SEMICOLON(NeedSemicolon)))[ToFunctionConcept]<<CLOSE_STAT(NeedCloseConcept)))[ToConceptDecl]
96 | (genericHead+opt(genericConstraint)+nonGenericDeclaration(NeedDeclaration))[ToGeneric]
97 ;
98
99 unit = ((UNIT(NeedUnit) >> ID(NeedID) << SEMICOLON(NeedSemicolon)) + list(opt(USES >> (ID(NeedID) + *(COMMA >> ID(NeedID))) << SEMICOLON(NeedSemicolon))) + list(*declaration))[ToUnit];
其次是C#版本的:
1 var ID = id("Developer.LanguageServices.NativeX.NativeXTokenizer.IdToken");
2 var STRING = id("Developer.LanguageServices.NativeX.NativeXTokenizer.StringToken");
3 var NUMBER = id("Developer.LanguageServices.NativeX.NativeXTokenizer.NumberToken");
4
5 var REFERENCE_TYPE = rule<NativeXReferenceType>("ReferenceType");
6 var FUNCTION_TYPE = rule<NativeXFunctionType>("FunctionType");
7 var INSTANCIATED_TYPE = rule<NativeXInstanciatedType>("InstanciatedType");
8 var PRIMITIVE_TYPE = rule<NativeXType>("PrimitiveType");
9 var TYPE = rule<NativeXType>("Type");
10
11 var PRIMITIVE = rule<NativeXPrimitiveExpression>("Primitive");
12 var INSTANCE_FUNCTION_REFERENCE = rule<NativeXInstanceFunctionExpression>("InstanceFunctionReference");
13 var INSTANCIATED_REFERENCE = rule<NativeXInstanciatedExpression>("InstanciatedReference");
14 var IDENTIFIER_REFERENCE = rule<NativeXReferenceExpression>("IdentifierReference");
15 var REFERENCE = rule<NativeXExpression>("Reference");
16 var RESULT = rule<NativeXFunctionResultExpression>("Result");
17 var EXCEPTION = rule<NativeXExceptionExpression>("Exception");
18 var CAST = rule<NativeXCastingExpression>("Casting");
19 var EXP0 = rule<NativeXExpression>("EXP0");
20 var EXP1 = rule<NativeXExpression>("EXP1");
21 var UNARY = rule<NativeXUnaryExpression>("Unary");
22 var EXP2 = rule<NativeXExpression>("EXP2");
23 var EXP_BINS = Enumerable.Range(3, 11).Select(i => rule<NativeXExpression>("EXP" + i.ToString())).ToArray();
24 var EXPRESSION = rule<NativeXExpression>("Expression");
25
26 var EMPTY_STATEMENT = rule<NativeXEmptyStatement>("EmptyStatement");
27 var EXPRESSION_STATEMENT = rule<NativeXExpressionStatement>("ExpressionStatement");
28 var VARIABLE_STATEMENT = rule<NativeXVariableStatement>("VariableStatement");
29 var IF_STATEMENT = rule<NativeXIfStatement>("IfStatement");
30 var BREAK_STATEMENT = rule<NativeXBreakStatement>("BreakStatement");
31 var CONTINUE_STATEMENT = rule<NativeXContinueStatement>("ContinueStatement");
32 var EXIT_STATEMENT = rule<NativeXReturnStatement>("ExitStatement");
33 var COMPOSITE_STATEMENT = rule<NativeXCompositeStatement>("CompositeStatement");
34 var DO_WHILE_STATEMENT = rule<NativeXWhileStatement>("DoWhileStatement");
35 var LOOP_STATEMENT = rule<NativeXWhileStatement>("LoopStatement");
36 var WHILE_DO_STATEMENT = rule<NativeXWhileStatement>("WhileDoStatement");
37 var FOR_STATEMENT = rule<NativeXForStatement>("ForStatement");
38 var TRY_CATCH_STATEMENT = rule<NativeXTryCatchStatement>("TryCatchStatement");
39 var THROW_STATEMENT = rule<NativeXThrowStatement>("ThrowStatement");
40 var STATEMENT = rule<NativeXStatement>("Statement");
41
42 var STRUCTURE_MEMBER = rule<NativeXNameTypePair>("StructureMemberItem");
43 var INSTANCE_FUNCTION = rule<NativeXNameExpressionPair>("InstanceFunctionItem");
44 var CONCEPT_FUNCTION = rule<NativeXNameTypePair>("ConceptFunctionItem");
45 var GENERIC_PARAMETER = rule<NativeXGenericParameter>("GenericParameterItem");
46 var GENERIC_CONSTRAINT = rule<NativeXGenericConstraint>("GenericConstraintItem");
47 var LINKING = rule<NativeXLinking>("Linking");
48
49 var FUNCTION_DECLARATION = rule<NativeXFunctionDeclaration>("FunctionDeclaration");
50 var TYPE_RENAME_DECLARATION = rule<NativeXTypeRenameDeclaration>("TypeRenameDeclaration");
51 var VARIABLE_DECLARATION = rule<NativeXVariableDeclaration>("VariableDeclaration");
52 var STRUCTURE_DECLARATION = rule<NativeXStructureDeclaration>("StructureDeclaration");
53 var INSTANCE_DECLARATION = rule<NativeXInstanceDeclaration>("InstanceDeclaration");
54 var CONCEPT_DECLARATION = rule<NativeXConceptDeclaration>("ConceptDeclaration");
55
56 var GENERIC_DECLARATION = rule<NativeXDeclaration>("GenericDeclaration");
57 var NON_GENERIC_DECLARATION = rule<NativeXDeclaration>("NonGenericDeclaration");
58 var DECLARATION = rule<NativeXDeclaration>("Declaration");
59
60 var USE = rule<NativeXUses>("UseUnitItem");
61 var UNIT = rule<NativeXUnit>("Unit");
62
63 {
64 USE.Infer(
65 ID["UnitName"]
66 );
67
68 UNIT.Infer(
69 tok("unit") + ID["Name"] + tok(";")
70 + opt(tok("uses") + list<NativeXUses>(tok(","), USE)["UsesUnits"] + tok(";"))
71 + list<NativeXDeclaration>(DECLARATION)["Declarations"]
72 );
73 }
74 {
75 STRUCTURE_MEMBER.Infer(
76 TYPE["Type"] + ID["Name"]
77 );
78
79 INSTANCE_FUNCTION.Infer(
80 ID["Name"] + tok("=") + EXPRESSION["Expression"]
81 );
82
83 CONCEPT_FUNCTION.Infer(
84 ID["Name"] + tok("=") + TYPE["Type"]
85 );
86
87 GENERIC_PARAMETER.Infer(
88 ID["ParameterName"]
89 );
90
91 GENERIC_CONSTRAINT.Infer(
92 ID["ParameterName"] + tok(":") + ID["ConceptName"]
93 );
94
95 LINKING.Infer(
96 tok("alias") + ID["LinkingAssembly"] + tok(".") + ID["LinkingSymbol"]
97 );
98 }
99 {
100 FUNCTION_DECLARATION.Infer(
101 opt(tok("foreign")["Foreign", "true"])
102 + tok("function") + TYPE["ReturnType"] + ID["Name"] + tok("(") + list<NativeXNameTypePair>(tok(","), STRUCTURE_MEMBER)["Parameters"] + tok(")")
103 + opt(LINKING["Linking"])
104 + (tok(";") | STATEMENT["Statement"])
105 );
106
107 VARIABLE_DECLARATION.Infer(
108 tok("variable") + TYPE["Type"] + ID["Name"] + opt(LINKING["Linking"]) + opt(tok("=") + EXPRESSION["Initializer"]) + tok(";")
109 );
110
111 TYPE_RENAME_DECLARATION.Infer(
112 tok("type") + ID["Name"] + tok("=") + TYPE["Type"] + tok(";")
113 );
114
115 STRUCTURE_DECLARATION.Infer(
116 tok("structure") + ID["Name"]
117 + (
118 tok(";")
119 | (
120 opt(LINKING["Linking"]) + tok("{") + list<NativeXNameTypePair>(ret(STRUCTURE_MEMBER) + tok(";"))["Members"] + tok("}")
121 )
122 )
123 );
124
125 INSTANCE_DECLARATION.Infer(
126 tok("instance") + REFERENCE_TYPE["Type"] + tok(":") + ID["ConceptName"]
127 + (
128 tok(";")
129 | (
130 tok("{") + list<NativeXNameExpressionPair>(ret(INSTANCE_FUNCTION) + tok(";"))["Functions"] + tok("}")
131 )
132 )
133 );
134
135 CONCEPT_DECLARATION.Infer(
136 tok("concept") + ID["ConceptType"] + tok(":") + ID["Name"] + opt(LINKING["Linking"]) + tok("{") + list<NativeXNameTypePair>(ret(CONCEPT_FUNCTION) + tok(";"))["Functions"] + tok("}")
137 );
138 }
139 {
140 NON_GENERIC_DECLARATION.Infer(
141 ret(FUNCTION_DECLARATION)
142 | ret(TYPE_RENAME_DECLARATION)
143 | ret(VARIABLE_DECLARATION)
144 | ret(STRUCTURE_DECLARATION)
145 | ret(INSTANCE_DECLARATION)
146 | ret(CONCEPT_DECLARATION)
147 );
148
149 GENERIC_DECLARATION.Infer(
150 tok("generic") + tok("<") + list<NativeXGenericParameter>(tok(","), GENERIC_PARAMETER)["GenericParameters"] + tok(">")
151 + opt(tok("where") + list<NativeXGenericConstraint>(tok(","), GENERIC_CONSTRAINT)["GenericConstraints"])
152 + ret(NON_GENERIC_DECLARATION)
153 );
154
155 DECLARATION.Infer(
156 ret(GENERIC_DECLARATION) | ret(NON_GENERIC_DECLARATION)
157 );
158 }
159 {
160 EMPTY_STATEMENT.Infer(
161 tok(";")
162 );
163
164 EXPRESSION_STATEMENT.Infer(
165 EXPRESSION["Expression"] + tok(";")
166 );
167
168 VARIABLE_STATEMENT.Infer(
169 tok("variable") + TYPE["Type"] + ID["Name"] + opt(tok("=") + EXPRESSION["Initializer"]) + tok(";")
170 );
171
172 IF_STATEMENT.Infer(
173 tok("if") + tok("(") + EXPRESSION["Condition"] + tok(")") + STATEMENT["TrueStatement"] + opt(tok("else") + STATEMENT["FalseStatement"])
174 );
175
176 BREAK_STATEMENT.Infer(
177 tok("break") + tok(";")
178 );
179
180 CONTINUE_STATEMENT.Infer(
181 tok("continue") + tok(";")
182 );
183
184 EXIT_STATEMENT.Infer(
185 tok("exit") + tok(";")
186 );
187
188 COMPOSITE_STATEMENT.Infer(
189 tok("{") + list<NativeXStatement>(STATEMENT)["Statements"] + tok("}")
190 );
191
192 DO_WHILE_STATEMENT.Infer(
193 tok("do") + STATEMENT["Statement"] + tok("while") + tok("(") + EXPRESSION["EndCondition"] + tok(")") + tok(";")
194 );
195
196 LOOP_STATEMENT.Infer(
197 tok("loop") + STATEMENT["Statement"]
198 );
199
200 WHILE_DO_STATEMENT.Infer(
201 tok("while") + tok("(") + EXPRESSION["BeginCondition"] + tok(")") + STATEMENT["Statement"] + opt(tok("when") + tok("(") + EXPRESSION["EndCondition"] + tok(")") + tok(";"))
202 );
203
204 FOR_STATEMENT.Infer(
205 tok("for") + list<NativeXStatement>(STATEMENT)["Initializer"]
206 + tok("when") + tok("(") + EXPRESSION["Condition"] + tok(")")
207 + tok("with") + list<NativeXStatement>(STATEMENT)["SideEffect"]
208 + tok("do") + STATEMENT["Statement"]
209 );
210
211 TRY_CATCH_STATEMENT.Infer(
212 tok("try") + STATEMENT["TryStatement"] + tok("catch") + STATEMENT["CatchStatement"]
213 );
214
215 THROW_STATEMENT.Infer(
216 tok("throw") + opt(EXPRESSION["ExceptionExpression"]) + tok(";")
217 );
218
219 STATEMENT.Infer(
220 ret(EMPTY_STATEMENT)
221 | ret(VARIABLE_STATEMENT)
222 | ret(IF_STATEMENT)
223 | ret(BREAK_STATEMENT)
224 | ret(CONTINUE_STATEMENT)
225 | ret(EXIT_STATEMENT)
226 | ret(COMPOSITE_STATEMENT)
227 | ret(DO_WHILE_STATEMENT)
228 | ret(LOOP_STATEMENT)
229 | ret(WHILE_DO_STATEMENT)
230 | ret(FOR_STATEMENT)
231 | ret(TRY_CATCH_STATEMENT)
232 | ret(THROW_STATEMENT)
233 | ret(EXPRESSION_STATEMENT)
234 );
235 }
236 {
237 PRIMITIVE.Infer(
238 STRING["Code"] | NUMBER["Code"] | toks("true", "false", "null")["Code"]
239 );
240
241 INSTANCE_FUNCTION_REFERENCE.Infer(
242 ID["ConceptName"] + tok("<") + TYPE["Type"] + tok(">") + tok(":") + tok(":") + ID["FunctionName"]
243 );
244
245 INSTANCIATED_REFERENCE.Infer(
246 ID["ReferencedName"] + tok("<") + list<NativeXType>(tok(","), TYPE)["GenericArguments"] + tok(">")
247 );
248
249 IDENTIFIER_REFERENCE.Infer(
250 ID["ReferencedName"]
251 );
252
253 REFERENCE.Infer(
254 ret(INSTANCE_FUNCTION_REFERENCE) | ret(INSTANCIATED_REFERENCE) | ret(IDENTIFIER_REFERENCE)
255 );
256
257 RESULT.Infer(
258 tok("result")
259 );
260
261 EXCEPTION.Infer(
262 tok("exception")
263 );
264
265 CAST.Infer(
266 tok("cast") + tok("<") + TYPE["Type"] + tok(">") + tok("(") + EXPRESSION["Operand"] + tok(")")
267 );
268
269 EXP0.Infer(
270 ret(RESULT) | ret(EXCEPTION) | ret(CAST) | ret(PRIMITIVE) | ret(REFERENCE) | tok("(") + ret(EXPRESSION) + tok(")")
271 );
272
273 EXP1.Infer(
274 ret(leftrecg(
275 EXP0,
276 g<NativeXSubscribeExpression>("Operand", tok("[") + EXPRESSION["Subscribe"] + tok("]")),
277 g<NativeXInvokeExpression>("Function", tok("(") + list<NativeXExpression>(tok(","), EXPRESSION)["Arguments"] + tok(")")),
278 g<NativeXMemberExpression>("Operand", tok(".") + ID["MemberName"]),
279 g<NativeXPointerMemberExpression>("Operand", tok("->") + ID["MemberName"]),
280 g<NativeXPostUnaryExpression>("Operand", toks("++", "--")["Operator"])
281 ))
282 );
283
284 UNARY.Infer(
285 ((toks("++", "--", "&", "*", "-", "!", "~")["Operator"])) + EXP2["Operand"]
286 );
287
288 EXP2.Infer(
289 ret(EXP1) | ret(UNARY)
290 );
291
292 {
293 string[][] binaryOperators = new string[][]{
294 new string[]{"*", "/", "%"},
295 new string[]{"+", "-"},
296 new string[]{"<<", ">>"},
297 new string[]{"<", "<=", ">", ">="},
298 new string[]{"==", "!="},
299 new string[]{"&"},
300 new string[]{"^"},
301 new string[]{"|"},
302 new string[]{"&&"},
303 new string[]{"||"},
304 new string[]{"+=", "-=", "*=", "/=", "%=", "<<=", ">>=", "&=", "/=", "&&=", "||=", "="}
305 };
306 ParserNode shiftNode = (tok("<") + tok("<"))["Operator", "\"<<\""] | (tok(">") + tok(">"))["Operator", "\">>\""];
307 ParserNode[] operatorNodes = binaryOperators
308 .Select(ops => ops.First() == "<<" ? shiftNode : toks(ops)["Operator"])
309 .ToArray();
310 ParserNode[] previousNode = new ParserNode[] { EXP2 }
311 .Concat(EXP_BINS.Take(EXP_BINS.Length - 1))
312 .ToArray();
313 for (int i = 0; i < EXP_BINS.Length; i++)
314 {
315 EXP_BINS[i].Infer(
316 ret(leftrec<NativeXBinaryExpression>(previousNode[i]["LeftOperand"], operatorNodes[i] + previousNode[i]["RightOperand"]))
317 );
318 }
319 }
320
321 EXPRESSION.Infer(
322 ret(EXP_BINS.Last())
323 );
324 }
325 {
326 REFERENCE_TYPE.Infer(
327 ID["ReferencedName"]
328 );
329
330 FUNCTION_TYPE.Infer(
331 tok("function") + TYPE["ReturnType"] + tok("(") + list<NativeXType>(tok(","), TYPE)["Parameters"] + tok(")")
332 );
333
334 INSTANCIATED_TYPE.Infer(
335 REFERENCE_TYPE["ElementType"] + tok("<") + list<NativeXType>(tok(","), TYPE)["GenericArguments"] + tok(">")
336 );
337
338 PRIMITIVE_TYPE.Infer(
339 ret(FUNCTION_TYPE) | ret(INSTANCIATED_TYPE) | ret(REFERENCE_TYPE)
340 );
341
342 TYPE.Infer(
343 ret(leftrecg(
344 PRIMITIVE_TYPE,
345 g<NativeXPointerType>("ElementType", tok("*")),
346 g<NativeXArrayType>("ElementType", tok("[") + PRIMITIVE["Size"] + tok("]"))
347 ))
348 );
349 }
我们可以看出C++的编译器版本的文法注重分析的过程以及报告错误,而C#的IDE版本的文法注重如何构建树。C++版本的文法可以直接被执行(如同boost::spirit),而C#版本的文法是拿来生成语法分析器的代码的(如同yacc和antlr)。C#版本的文法虽然完整了,不过里面还没有容错的方法。一般来说容错有两种关键内容,分别是在遇到某些记号序列的时候强制分析下去(自动纠正错误),和在遇到某些记号序列的时候强制分析结束(譬如表达式遇到了“)”就肯定是要结束的了,如果出现“structure”就要直接回溯到最上层了,因为接下去就是structure的声明,函数都结束了……)。IDE版本的文法需要能够高度容错的原因是它分析的往往是写了一半的代码,而且还要在适当的时候能给出适当的提示,因此就要求这个语法分析器可以分析一些残缺不全的代码并且给出相应的残缺不全的语法树,但是结构必须是大体上正确才行。
这一步研究结束之后,基本上IDE就只剩下界面的问题了。反正用一颗树来做语义分析已经是炉火纯青了,不过我们知道那些用来做智能提示的界面其实也不是那么好做的……
接下来的研究重点就是如何将容错的具体方法在文法上表达出来,以及生成容错相关的代码了。
posted on 2010-10-22 20:34
陈梓瀚(vczh) 阅读(5720)
评论(4) 编辑 收藏 引用 所属分类:
开发自己的IDE