1
2
3
4
5
6 using System.Lex;
7 using Cm.Ast;
8 using ParserFileTokens;
9
10 parser ParserFileParser
11 {
12 uselexer ParserFileLexer;
13 main;
14
15 using IdentifierParser.QualifiedId;
16 using IdentifierParser.Identifier;
17 using TypeExprParser.TypeExpr;
18 using ExpressionParser.ExpressionList;
19 using StatementParser.CompoundStatement;
20
21 ParserFile(ParsingContext* parsingContext, var UniquePtr<soulcm.scmpg.ParserFile> parserFile) : soulcm.scmpg.ParserFile*
22 ::= (empty{ parserFile.Reset(new soulcm.scmpg.ParserFile(lexer.FileName())); } Declaration(parserFile.Get(), parsingContext):declaration*)
23 {
24 return parserFile.Release();
25 }
26 ;
27
28 Declaration(soulcm.scmpg.ParserFile* parserFile, ParsingContext* parsingContext)
29 ::= UsingDirective(parsingContext):usingDirective{ parserFile->AddUsingDirective(usingDirective); }
30 | ParserDeclaration(parsingContext):parserDeclaration{ parserFile->AddParser(parserDeclaration); }
31 ;
32
33 UsingDirective(ParsingContext* ctx) : Node*
34 ::= UsingAliasDirective(ctx):usingAlias{ return usingAlias; }
35 | UsingNamespaceDirective(ctx):usingNs{ return usingNs; }
36 ;
37
38 UsingAliasDirective(ParsingContext* ctx, var Span s) : Node*
39 ::= USING{ s = span; } Identifier(ctx):id ASSIGN QualifiedId(ctx):qid! SEMICOLON!
40 {
41 s.end = span.end;
42 return new AliasNode(s, ctx->ModuleId(), id, qid);
43 }
44 ;
45
46 UsingNamespaceDirective(ParsingContext* ctx, var Span s) : Node*
47 ::= USING{ s = span; } QualifiedId(ctx):ns! SEMICOLON!
48 {
49 s.end = span.end;
50 return new NamespaceImportNode(s, ctx->ModuleId(), ns);
51 }
52 ;
53
54 ParserDeclaration(ParsingContext* parsingContext, var UniquePtr<soulcm.scmpg.GrammarParser> grammarParser) : soulcm.scmpg.GrammarParser*
55 ::= (PARSER ID{ grammarParser.Reset(new soulcm.scmpg.GrammarParser(lexer.GetMatch(span), u"")); } LBRACE! Statement(grammarParser.Get(), parsingContext):statement* RBRACE!)
56 {
57 return grammarParser.Release();
58 }
59 ;
60
61 Statement(soulcm.scmpg.GrammarParser* grammarParser, ParsingContext* parsingContext)
62 ::= MainStatement(grammarParser):mainStatement
63 | StartStatement(grammarParser):startStatement
64 | NothrowStatement(grammarParser):nothrowStatement
65 | FarthestErrorStatement(grammarParser):farthestErrorStatement
66 | StateStatement(grammarParser):stateStatement
67 | UsingStatement(grammarParser):usingStatement
68 | LexerStatement(grammarParser):lexerStatement
69 | RuleInfoStatement(grammarParser):ruleInfoStatement
70 | RuleStatement(grammarParser, parsingContext):ruleStatement
71 ;
72
73 MainStatement(soulcm.scmpg.GrammarParser* grammarParser)
74 ::= MAIN SEMICOLON!{ grammarParser->SetMain(); }
75 ;
76
77 StartStatement(soulcm.scmpg.GrammarParser* grammarParser)
78 ::= START SEMICOLON!{ grammarParser->SetStart(); }
79 ;
80
81 NothrowStatement(soulcm.scmpg.GrammarParser* grammarParser)
82 ::= NOTHROW SEMICOLON!{ grammarParser->SetNothrow(); }
83 ;
84
85 FarthestErrorStatement(soulcm.scmpg.GrammarParser* grammarParser)
86 ::= FARTHEST_ERROR SEMICOLON!{ grammarParser->SetFarthestError(); }
87 ;
88
89 StateStatement(soulcm.scmpg.GrammarParser* grammarParser)
90 ::= STATE SEMICOLON!{ grammarParser->SetState(); }
91 ;
92
93 UsingStatement(soulcm.scmpg.GrammarParser* grammarParser)
94 ::= USING UsingQualifiedId:parserId! SEMICOLON!{ grammarParser->AddUsing(parserId); }
95 ;
96
97 UsingQualifiedId(var Span s) : ustring
98 ::= (ID{ s = span; } (DOT ID{ s.end = span.end; })*){ return lexer.GetMatch(s); }
99 ;
100
101 LexerStatement(soulcm.scmpg.GrammarParser* grammarParser, var ustring lexerName)
102 ::= USELEXER ID!{ lexerName = lexer.GetMatch(span); } SEMICOLON!{ grammarParser->SetLexer(lexerName); }
103 ;
104
105 RuleInfoStatement(soulcm.scmpg.GrammarParser* grammarParser)
106 ::= RULEINFO LBRACE! (RuleInfo(grammarParser):ruleInfo % COMMA)? RBRACE!
107 ;
108
109 RuleInfo(soulcm.scmpg.GrammarParser* grammarParser, var ustring ruleName, var ustring ruleInfo)
110 ::= LPAREN ID!{ ruleName = lexer.GetMatch(span); } COMMA! STRINGLIT!{ ruleInfo = soulcm.scmpg.ParseStringLiteral(lexer.FileName(), lexer.GetToken(pos)); } RPAREN!
111 {
112 grammarParser->AddRuleInfo(ruleName, ruleInfo);
113 }
114 ;
115
116 RuleStatement(soulcm.scmpg.GrammarParser* grammarParser, ParsingContext* parsingContext, var UniquePtr<soulcm.scmpg.RuleParser> rule)
117 ::= ID{ ustring id = lexer.GetMatch(span); rule.Reset(new soulcm.scmpg.RuleParser(id)); } ParametersAndVariables(rule.Get(), parsingContext):paramsAndVars?
118 ReturnType(parsingContext):returnType? PRODUCES RuleBody(parsingContext):definition! SEMICOLON!
119 {
120 rule->SetDefinition(definition);
121 rule->SetReturnType(returnType);
122 grammarParser->AddRule(rule.Release());
123 }
124 ;
125
126 ParametersAndVariables(soulcm.scmpg.RuleParser* rule, ParsingContext* parsingContext)
127 ::= LPAREN (ParamOrVariable(parsingContext):paramOrVariable{ rule->AddParamOrVariable(paramOrVariable); } % COMMA)? RPAREN!
128 ;
129
130 ParamOrVariable(ParsingContext* parsingContext) : soulcm.scmpg.Parameter*
131 ::= VAR TypeExpr(parsingContext):varType Identifier(parsingContext):varName{ return new soulcm.scmpg.Variable(varType, varName); }
132 | TypeExpr(parsingContext):paramType Identifier(parsingContext):paramName{ return new soulcm.scmpg.Parameter(paramType, paramName); }
133 ;
134
135 ReturnType(ParsingContext* parsingContext) : Node*
136 ::= COLON TypeExpr(parsingContext):type{ return type; }
137 ;
138
139 RuleBody(ParsingContext* parsingContext) : soulcm.scmpg.Parser*
140 ::= Alternative(parsingContext):alt{ return alt; }
141 ;
142
143 Alternative(ParsingContext* parsingContext, var UniquePtr<soulcm.scmpg.Parser> value) : soulcm.scmpg.Parser*
144 ::= (Sequence(parsingContext):left{ value.Reset(left); } (BITOR Sequence(parsingContext):right!{ value.Reset(new soulcm.scmpg.AlternativeParser(value.Release(), right)); })*)
145 {
146 return value.Release();
147 }
148 ;
149
150 Sequence(ParsingContext* parsingContext, var UniquePtr<soulcm.scmpg.Parser> value) : soulcm.scmpg.Parser*
151 ::= (Difference(parsingContext):left{ value.Reset(left); } (Difference(parsingContext):right{ value.Reset(new soulcm.scmpg.SequenceParser(value.Release(), right)); })*)
152 {
153 return value.Release();
154 }
155 ;
156
157 Difference(ParsingContext* parsingContext, var UniquePtr<soulcm.scmpg.Parser> value) : soulcm.scmpg.Parser*
158 ::= (List(parsingContext):left{ value.Reset(left); } (MINUS List(parsingContext):right!{ value.Reset(new soulcm.scmpg.DifferenceParser(value.Release(), right)); })*)
159 {
160 return value.Release();
161 }
162 ;
163
164 List(ParsingContext* parsingContext, var UniquePtr<soulcm.scmpg.Parser> value) : soulcm.scmpg.Parser*
165 ::= (Postfix(parsingContext):left{ value.Reset(left); } (REM Postfix(parsingContext):right!{ value.Reset(new soulcm.scmpg.ListParser(value.Release(), right)); })?)
166 {
167 return value.Release();
168 }
169 ;
170
171 Postfix(ParsingContext* parsingContext, var UniquePtr<soulcm.scmpg.Parser> value) : soulcm.scmpg.Parser*
172 ::=
173 ( Primary(parsingContext):primary{ value.Reset(primary); }
174 ( STAR{ value.Reset(new soulcm.scmpg.KleeneParser(value.Release())); }
175 | PLUS{ value.Reset(new soulcm.scmpg.PositiveParser(value.Release())); }
176 | QUEST{ value.Reset(new soulcm.scmpg.OptionalParser(value.Release())); }
177 )?
178 )
179 {
180 return value.Release();
181 }
182 ;
183
184 Primary(ParsingContext* parsingContext, var UniquePtr<soulcm.scmpg.Parser> value) : soulcm.scmpg.Parser*
185 ::=
186 (
187 ( RuleCall(parsingContext):ruleCall{ value.Reset(ruleCall); }
188 | Primitive:primitive{ value.Reset(primitive); }
189 | Grouping(parsingContext):grouping{ value.Reset(grouping); }
190 )
191 (
192 EXCLAMATION{ value.Reset(new soulcm.scmpg.ExpectationParser(value.Release())); }
193 )?
194 (
195 (
196 (CompoundStatement(parsingContext):successCode
197 (DIV CompoundStatement(parsingContext):failureCode)?){ value.Reset(new soulcm.scmpg.ActionParser(successCode, failureCode, value.Release())); }
198 )
199 )?
200 )
201 {
202 return value.Release();
203 }
204 ;
205
206 RuleCall(ParsingContext* parsingContext, var ustring ruleName, var UniquePtr<InvokeNode> invoke, var long nonterminalPos) : soulcm.scmpg.Parser*
207 ::= Nonterminal:nt{ ruleName = nt; nonterminalPos = pos; invoke.Reset(new InvokeNode(Span(), parsingContext->ModuleId())); }
208 (LPAREN{ pass = NoWhiteSpaceBetweenTokens(lexer.GetToken(nonterminalPos), lexer.GetToken(pos)); }
209 ExpressionList(parsingContext, invoke.Get()):args RPAREN)? COLON ID!
210 {
211 ustring name = lexer.GetMatch(span);
212 soulcm.scmpg.NonterminalParser* nonterminalParser = new soulcm.scmpg.NonterminalParser(name, ruleName);
213 nonterminalParser->SetArguments(invoke.Get());
214 return nonterminalParser;
215 }
216 ;
217
218 Nonterminal : ustring
219 ::= ID{ return lexer.GetMatch(span); }
220 ;
221
222 Primitive : soulcm.scmpg.Parser*
223 ::= EMPTY
224 {
225 return new soulcm.scmpg.EmptyParser();
226 }
227 | ANY
228 {
229 return new soulcm.scmpg.AnyParser();
230 }
231 | ID
232 {
233 ustring tokenName = lexer.GetMatch(span);
234 return new soulcm.scmpg.TokenParser(tokenName);
235 }
236 | CHARLIT
237 {
238 uchar charLit = soulcm.scmpg.ParseCharLiteral(lexer.FileName(), lexer.GetToken(pos));
239 return new soulcm.scmpg.CharParser(charLit);
240 }
241 | STRINGLIT
242 {
243 ustring strLit = soulcm.scmpg.ParseStringLiteral(lexer.FileName(), lexer.GetToken(pos));
244 if (strLit.Length() > 0 && strLit[0] == '[' && strLit[strLit.Length() - 1] == ']')
245 {
246 soulcm.scmpg.CharSet charSet = soulcm.scmpg.ParseCharSet(lexer.FileName(), lexer.GetToken(pos), strLit);
247 return new soulcm.scmpg.CharSetParser(charSet);
248 }
249 else
250 {
251 return new soulcm.scmpg.StringParser(strLit);
252 }
253 }
254 ;
255
256 Grouping(ParsingContext* parsingContext) : soulcm.scmpg.Parser*
257 ::= (LPAREN Alternative(parsingContext):alt RPAREN!){ return new soulcm.scmpg.GroupingParser(alt); }
258 ;
259 }