1 // =================================
 2 // Copyright (c) 2021 Seppo Laakko
 3 // Distributed under the MIT license
 4 // =================================
 5 
 6 using RexTokens;
 7 
 8 parser RexParser
 9 {
10     uselexer RexLexer;
11 
12     main;
13 
14     RegularExpression(System.RegularExpressions.Context* context) : System.RegularExpressions.Nfa
15         ::= Alternative(context):alternative{ return alternative; }
16         ;
17 
18     Alternative(System.RegularExpressions.Context* context, var System.RegularExpressions.Nfa value) : System.RegularExpressions.Nfa
19         ::= (Catenation(context):left{ value = left; } (ALT Catenation(context):right!{ value = System.RegularExpressions.Alt(*context, value, right); })*)
20         {
21             return value;
22         }
23         ;
24 
25     Catenation(System.RegularExpressions.Context* context, var System.RegularExpressions.Nfa value) : System.RegularExpressions.Nfa
26         ::= (Repetition(context):left{ value = left; } (Repetition(context):right{ value = System.RegularExpressions.Cat(value, right); })*)
27         {
28             return value;
29         }
30         ;
31 
32     Repetition(System.RegularExpressions.Context* context, var System.RegularExpressions.Nfa value) : System.RegularExpressions.Nfa
33         ::=
34         (   Primary(context):left{ value = left; }
35             (   STAR{ value = System.RegularExpressions.Kleene(*context, value); }
36             |   PLUS{ value = System.RegularExpressions.Pos(*context, value); }
37             |   QUEST{ value = System.RegularExpressions.Opt(*context, value); }
38             )?
39         )
40         {
41             return value;
42         }
43         ;
44 
45     Primary(System.RegularExpressions.Context* context, var System.RegularExpressions.Nfa value) : System.RegularExpressions.Nfa
46         ::=
47         (   LPAREN Alternative(context):alt!{ value = alt; } RPAREN!
48         |   ESCAPE{ value = System.RegularExpressions.MakeNfa(*context, context->MakeChar(System.RegularExpressions.MakeEscapeValue(lexer.FileName(), lexer.GetToken(pos)))); }
49         |   INVERSE{ value = System.RegularExpressions.MakeNfa(*context, context->MakeChar('^')); }
50         |   MINUS{ value = System.RegularExpressions.MakeNfa(*context, context->MakeChar('-')); }
51         |   CHAR{ ustring match = lexer.GetMatch(span); value = System.RegularExpressions.MakeNfa(*context, context->MakeChar(match[0])); }
52         |   DOT{ value = System.RegularExpressions.MakeNfa(*context, context->MakeAny()); }
53         |   Class(context):cls{ value = System.RegularExpressions.MakeNfa(*context, cls); }
54         )
55         {
56             return value; 
57         }
58         ;
59 
60     Class(System.RegularExpressions.Context* context, var System.RegularExpressions.Class* cls) : System.RegularExpressions.Class*
61         ::= (LBRACKET{ cls = context->MakeClass(); } ((INVERSE{ cls->SetInverse(); })? (Range(context):r{ cls->AddSymbol(r); })*) RBRACKET!)
62         {
63             return cls;
64         }
65         ;
66 
67     Range(System.RegularExpressions.Context* context, var System.RegularExpressions.Symbol* symbol) : System.RegularExpressions.Symbol*
68         ::= (Char:s (MINUS Char:e{ symbol = context->MakeRange(s, e); } | empty{ symbol = context->MakeChar(s); }))
69         {
70             return symbol;
71         }
72         ;
73 
74     Char : uchar
75         ::= LPAREN{ return '('; }
76         |   RPAREN{ return ')'; }
77         |   LBRACKET{ return '['; }
78         |   ALT{ return '|'; }
79         |   STAR{ return '*'; }
80         |   PLUS{ return '+'; }
81         |   QUEST{ return '?'; }
82         |   DOT{ return '.'; }
83         |   ESCAPE{ return System.RegularExpressions.MakeEscapeValue(lexer.FileName(), lexer.GetToken(pos)); }
84         |   INVERSE{ return '^'; }
85         |   MINUS{ return '-'; }
86         |   CHAR{ ustring match = lexer.GetMatch(span); return match[0]; }
87         ;
88 }