Merge branch 'master' of github.com:systemed/potlatch2
[potlatch2.git] / it / sephiroth / expr / Parser.as
1 package it.sephiroth.expr
2 {
3         import it.sephiroth.expr.ast.AddExpression;
4         import it.sephiroth.expr.ast.CallExpression;
5         import it.sephiroth.expr.ast.DivExpression;
6         import it.sephiroth.expr.ast.IExpression;
7         import it.sephiroth.expr.ast.IdentExpression;
8         import it.sephiroth.expr.ast.MulExpression;
9         import it.sephiroth.expr.ast.NumberExpression;
10         import it.sephiroth.expr.ast.SubExpression;
11         import it.sephiroth.expr.ast.UnaryMinusExpression;
12         import it.sephiroth.expr.ast.UnaryPlusExpression;
13         import it.sephiroth.expr.errors.ExpressionError;
14         
15         public class Parser
16         {
17                 private var _token: Token;
18                 private var _scanner: Scanner;
19                 private var _symbols: SymbolTable;
20                 
21                 public function Parser( scanner: Scanner )
22                 {
23                         _scanner = scanner;
24                         _symbols = new SymbolTable();
25                 }
26                 
27                 public function parse(): CompiledExpression
28                 {
29                         _token = _scanner.nextToken();
30                         var expr: IExpression = parseExpression();
31                         
32                         if( _token.type == TokenType.EOF )
33                         {
34                                 return new CompiledExpression( expr, _symbols );
35                         }else
36                         {
37                                 throw new ExpressionError( "Unexpected token: " + _token );
38                         }
39                 }
40                 
41                 private function parseExpression(): IExpression
42                 {
43                         var operator: int;
44                         var left: IExpression;
45                         var right: IExpression;
46                         
47                         left = parseTerm();
48                         
49                         while( ( _token.type == TokenType.ADD ) || ( ( _token.type == TokenType.SUB ) ) )
50                         {
51                                 operator = _token.type;
52                                 _token = _scanner.nextToken();
53                                 right = parseTerm();
54                                 
55                                 if( operator == TokenType.ADD )
56                                 {
57                                         left = new AddExpression( left, right );
58                                 }else
59                                 {
60                                         left = new SubExpression( left, right );
61                                 }
62                         }
63                         
64                         return left;
65                 }
66                 
67                 private function parseTerm(): IExpression
68                 {
69                         var operator: int;
70                         var left: IExpression;
71                         var right: IExpression;
72                         
73                         left = parseFactor();
74                         
75                         while( ( _token.type == TokenType.MUL ) || ( ( _token.type == TokenType.DIV ) ) )
76                         {
77                                 operator = _token.type;
78                                 _token = _scanner.nextToken();
79                                 right = parseFactor();
80                                 
81                                 if( operator == TokenType.MUL )
82                                 {
83                                         left = new MulExpression( left, right );
84                                 }else
85                                 {
86                                         left = new DivExpression( left, right );
87                                 }
88                         }
89                         
90                         return left;
91                 }
92                 
93                 private function parseFactor(): IExpression
94                 {
95                         var tree: IExpression;
96                         var unary: Array = new Array();
97                         
98                         while( ( _token.type == TokenType.ADD ) || ( ( _token.type == TokenType.SUB ) ) )
99                         {
100                                 unary.push( _token );
101                                 _token = _scanner.nextToken();
102                         }
103                         
104                         switch( _token.type )
105                         {
106                                 case TokenType.NUM:
107                                         tree = new NumberExpression( _token.value );
108                                         _token = _scanner.nextToken();
109                                         break;
110                                 
111                                 case TokenType.IDENT:
112                                         var ident_name: String = _token.value;
113                                         var ident: Ident = _symbols.findAndAdd( ident_name );
114                                         tree = new IdentExpression( ident );
115                                         _token = _scanner.nextToken();
116                                         
117                                         if( _token.type == TokenType.LEFT_PAR )
118                                         {
119                                                 var arguments: Array = new Array();
120                                                 _token = _scanner.nextToken();
121                                                 
122                                                 if( _token.type != TokenType.RIGHT_PAR )
123                                                 {
124                                                         do
125                                                         {
126                                                                 arguments.push( parseExpression() );
127                                                         } while( _token.type == TokenType.COMMA );
128                                                         
129                                                         if( _token.type != TokenType.RIGHT_PAR )
130                                                         {
131                                                                 throw new ExpressionError( "Unexpected token " + _token + ", expecting )" );
132                                                         }else
133                                                         {
134                                                                 _token = _scanner.nextToken();
135                                                         }
136                                                 }
137                                                 
138                                                 tree = new CallExpression( ident, arguments );
139                                         }
140                                         
141                                         break;
142                                 
143                                 case TokenType.LEFT_PAR:
144                                         _token = _scanner.nextToken();
145                                         tree = parseExpression();
146                                         if( _token.type == TokenType.RIGHT_PAR )
147                                         {
148                                                 _token = _scanner.nextToken();
149                                         }else
150                                         {
151                                                 throw new ExpressionError( "Unexpected token " + _token + ", expecting )" );
152                                         }
153                                         break;
154                                 
155                                 default:
156                                         throw new ExpressionError( "Unexpected token " + _token );
157                                         break;
158                                         
159                         }
160                         
161                         while( unary.length > 0 )
162                         {
163                                 if( unary.pop().type == TokenType.ADD )
164                                 {
165                                         tree = new UnaryPlusExpression( tree );
166                                 }else
167                                 {
168                                         tree = new UnaryMinusExpression( tree );
169                                 }
170                         }
171                         
172                         return tree;
173                 }
174
175         }
176 }