1
2
3
4
5
6 using RegExTokens;
7
8 parser RegExParser
9 {
10 uselexer RegExLexer;
11
12 main;
13
14 RegularExpression(soulcm.scmlg.LexerContext* lexerContext) : soulcm.scmlg.Nfa
15 ::= Alternative(lexerContext):alternative{ return alternative; }
16 ;
17
18 Alternative(soulcm.scmlg.LexerContext* lexerContext, var soulcm.scmlg.Nfa value) : soulcm.scmlg.Nfa
19 ::= (Catenation(lexerContext):left{ value = left; } (ALT Catenation(lexerContext):right!{ value = soulcm.scmlg.Alt(*lexerContext, value, right); })*)
20 {
21 return value;
22 }
23 ;
24
25 Catenation(soulcm.scmlg.LexerContext* lexerContext, var soulcm.scmlg.Nfa value) : soulcm.scmlg.Nfa
26 ::= (Repetition(lexerContext):left{ value = left; } (Repetition(lexerContext):right{ value = soulcm.scmlg.Cat(value, right); })*)
27 {
28 return value;
29 }
30 ;
31
32 Repetition(soulcm.scmlg.LexerContext* lexerContext, var soulcm.scmlg.Nfa value) : soulcm.scmlg.Nfa
33 ::=
34 ( Primary(lexerContext):left{ value = left; }
35 ( STAR{ value = soulcm.scmlg.Kleene(*lexerContext, value); }
36 | PLUS{ value = soulcm.scmlg.Pos(*lexerContext, value); }
37 | QUEST{ value = soulcm.scmlg.Opt(*lexerContext, value); }
38 )?
39 )
40 {
41 return value;
42 }
43 ;
44
45 Primary(soulcm.scmlg.LexerContext* lexerContext, var soulcm.scmlg.Nfa value) : soulcm.scmlg.Nfa
46 ::=
47 ( LPAREN Alternative(lexerContext):alt!{ value = alt; } RPAREN!
48 | ESCAPE{ value = soulcm.scmlg.MakeNfa(*lexerContext, lexerContext->MakeChar(soulcm.scmlg.MakeEscapeValue(lexer.FileName(), lexer.GetToken(pos)))); }
49 | INVERSE{ value = soulcm.scmlg.MakeNfa(*lexerContext, lexerContext->MakeChar('^')); }
50 | MINUS{ value = soulcm.scmlg.MakeNfa(*lexerContext, lexerContext->MakeChar('-')); }
51 | CHAR{ ustring match = lexer.GetMatch(span); value = soulcm.scmlg.MakeNfa(*lexerContext, lexerContext->MakeChar(match[0])); }
52 | DOT{ value = soulcm.scmlg.MakeNfa(*lexerContext, lexerContext->MakeAny()); }
53 | Class(lexerContext):cls{ value = soulcm.scmlg.MakeNfa(*lexerContext, cls); }
54 | ExpressionReference:ref{ value = lexerContext->MakeExpr(ref); }
55 )
56 {
57 return value;
58 }
59 ;
60
61 Class(soulcm.scmlg.LexerContext* lexerContext, var soulcm.scmlg.Class* cls) : soulcm.scmlg.Class*
62 ::= (LBRACKET{ cls = lexerContext->MakeClass(); } ((INVERSE{ cls->SetInverse(); })? (Range(lexerContext):r{ cls->AddSymbol(r); })*) RBRACKET!)
63 {
64 return cls;
65 }
66 ;
67
68 Range(soulcm.scmlg.LexerContext* lexerContext, var soulcm.scmlg.Symbol* symbol) : soulcm.scmlg.Symbol*
69 ::= (Char:s (MINUS Char:e{ symbol = lexerContext->MakeRange(s, e); } | empty{ symbol = lexerContext->MakeChar(s); }))
70 {
71 return symbol;
72 }
73 ;
74
75 Char : uchar
76 ::= LPAREN{ return '('; }
77 | RPAREN{ return ')'; }
78 | LBRACKET{ return '['; }
79 | LBRACE{ return '{'; }
80 | RBRACE{ return '}'; }
81 | ALT{ return '|'; }
82 | STAR{ return '*'; }
83 | PLUS{ return '+'; }
84 | QUEST{ return '?'; }
85 | DOT{ return '.'; }
86 | ESCAPE{ return soulcm.scmlg.MakeEscapeValue(lexer.FileName(), lexer.GetToken(pos)); }
87 | INVERSE{ return '^'; }
88 | MINUS{ return '-'; }
89 | CHAR{ ustring match = lexer.GetMatch(span); return match[0]; }
90 ;
91
92 ExpressionReference(var Span s) : ustring
93 ::= LBRACE{ s = span; } CHAR+ RBRACE{ s.end = span.end; return soulcm.scmlg.MakeExprRefId(lexer.FileName(), lexer.GetMatch(s), lexer.GetToken(pos).line); }
94 ;
95
96 ruleinfo
97 {
98 (RegularExpression, "regular expression"), (Alternative, "alternative"), (Catenation, "catenation"), (Repetition, "repetition"), (Primary, "primary expression"),
99 (Class, "regular class definition"), (Range, "range"), (Char, "character"), (ExpressionReference, "regular expression reference")
100 }
101 }