1+ namespace BooleanExpressionParser ;
2+
3+ class Parser
4+ {
5+ public Parser ( )
6+ {
7+ }
8+
9+ public IEnumerable < Token > ParseTokens ( IEnumerable < Token > tokens )
10+ {
11+ var output = new Queue < Token > ( ) ;
12+ var stack = new Stack < Token > ( ) ;
13+
14+ foreach ( var token in tokens )
15+ {
16+ switch ( token . Type )
17+ {
18+ case Token . TokenType . IDENTIFIER :
19+ output . Enqueue ( token ) ;
20+ break ;
21+
22+ case Token . TokenType . BINARY_OPERATOR :
23+ case Token . TokenType . UNARY_OPERATOR :
24+ while ( ( stack . Count > 0 && stack . Peek ( ) . Type != Token . TokenType . OPEN_PAREN ) /* && CHECK PRECEDENCE HERE */ )
25+ {
26+ output . Enqueue ( stack . Pop ( ) ) ;
27+ }
28+ stack . Push ( token ) ;
29+ break ;
30+
31+ case Token . TokenType . OPEN_PAREN :
32+ stack . Push ( token ) ;
33+ break ;
34+
35+ case Token . TokenType . CLOSE_PAREN :
36+ while ( stack . Count > 0 && stack . Peek ( ) . Type != Token . TokenType . OPEN_PAREN )
37+ {
38+ output . Enqueue ( stack . Pop ( ) ) ;
39+ }
40+
41+ if ( stack . Peek ( ) . Type == Token . TokenType . OPEN_PAREN )
42+ {
43+ stack . Pop ( ) ;
44+ if ( stack . Count > 0 && ( stack . Peek ( ) . Type == Token . TokenType . UNARY_OPERATOR || stack . Peek ( ) . Type == Token . TokenType . BINARY_OPERATOR ) )
45+ {
46+ output . Enqueue ( stack . Pop ( ) ) ;
47+ }
48+ }
49+ break ;
50+ }
51+ }
52+
53+ while ( stack . Count > 0 )
54+ {
55+ if ( stack . Peek ( ) . Type == Token . TokenType . OPEN_PAREN )
56+ {
57+ throw new Exception ( "OPEN_PAREN on operator stack." ) ;
58+ }
59+ output . Enqueue ( stack . Pop ( ) ) ;
60+ }
61+
62+ return output ;
63+ }
64+
65+ public Ast GrowAst ( IEnumerable < Token > tokens )
66+ {
67+ var stack = new Stack < Node > ( ) ;
68+ var variables = new List < string > ( ) ;
69+
70+ foreach ( var token in tokens )
71+ {
72+ switch ( token . Type )
73+ {
74+ case Token . TokenType . IDENTIFIER :
75+ stack . Push ( new VariableNode ( token . Value ) ) ;
76+ if ( ! variables . Contains ( token . Value ) ) variables . Add ( token . Value ) ;
77+ break ;
78+
79+ case Token . TokenType . BINARY_OPERATOR :
80+ if ( stack . Count < 2 ) throw new Exception ( $ "2 parameters needed for operator ${ token . Type } ") ;
81+
82+ if ( token . Value == "AND" )
83+ stack . Push ( new AndOperatorNode ( stack . Pop ( ) , stack . Pop ( ) ) ) ;
84+ else
85+ stack . Push ( new OrOperatorNode ( stack . Pop ( ) , stack . Pop ( ) ) ) ;
86+ break ;
87+
88+ case Token . TokenType . UNARY_OPERATOR :
89+ if ( stack . Count < 1 ) throw new Exception ( $ "1 parameter needed for operator ${ token . Type } ") ;
90+
91+ if ( token . Value == "NOT" )
92+ stack . Push ( new NotOperatorNode ( stack . Pop ( ) ) ) ;
93+ break ;
94+ }
95+ }
96+
97+ if ( stack . Count != 1 ) throw new Exception ( "Expression invalid - stack not empty" ) ;
98+
99+ var root = stack . Pop ( ) ;
100+
101+ return new Ast ( root , variables ) ;
102+ }
103+ }
0 commit comments