Merge pull request #820 from brendanzagaeski/master
[mono.git] / mcs / class / Microsoft.Build / Microsoft.Build.Internal / ExpressionParser.jay
1 //
2 // ExpressionParser.jay
3 //
4 // Author:
5 //   Atsushi Enomoto (atsushi@xamarin.com)
6 //
7 // Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 %{
29
30 using System;
31 using System.Text;
32 using Microsoft.Build.Evaluation;
33 using Microsoft.Build.Exceptions;
34 using Microsoft.Build.Framework;
35
36 /*
37
38 Pseudo formal syntax for .NET 4.0 expression:
39
40 Condition = Expression
41 Include = Expression*
42
43  Expression
44         BooleanLiteral
45                 TrueLiteral
46                 FalseLiteral
47         BinaryExpression
48                 Expression "==" Expression
49                 Expression "!=" Expression
50                 Expression ">" Expression
51                 Expression ">=" Expression
52                 Expression "<" Expression
53                 Expression "<=" Expression
54                 Expression "And" Expression
55                 Expression "Or" Expression
56         UnaryExpression
57                 "!" Expression
58         PropertyExpression
59                 "$(" PropertyApplication ")"
60         ItemExpression
61                 "@(" ItemApplication ")"
62         MetadataBatchingExpression
63                 "%(" MetadataBatchingApplication ")"
64   StringLiteralOrFunction
65                 StringLiteralOrFunctionName ( "(" FunctionArguments ")" )?
66
67 .NET error messages are so detailed which is something like "you forgot '(' after '$' ?" - so
68 it is likely that the MS tokenizer is hand-written.
69
70 */
71
72 namespace Microsoft.Build.Internal.Expressions
73 {
74         class ExpressionParser
75         {
76                 static readonly int yacc_verbose_flag = Environment.GetEnvironmentVariable ("MONO_MSBUILD_PARSER_DEBUG") == "1" ? 1 : 0;
77
78                 object debug_obj = yacc_verbose_flag == 0 ? null : new yydebug.yyDebugSimple ();
79                 
80                 public ExpressionList Parse (string source, ExpressionValidationType validationType)
81                 {
82                         var tokenizer = new ExpressionTokenizer (source, validationType);
83                         return (ExpressionList) yyparse (tokenizer, debug_obj);
84                 }
85                 
86                 BinaryExpression Binary (Operator op, object left, object right)
87                 {
88                         return new BinaryExpression () { Operator = op, Left = (Expression) left, Right = (Expression) right, Location = (ILocation) left };
89                 }
90 %}
91
92 %token TRUE_LITERAL
93 %token FALSE_LITERAL
94 %token STRING_LITERAL
95 %token EQ // ==
96 %token NE // !=
97 %token GT // >
98 %token GE // >=
99 %token LT // <
100 %token LE // <=
101 %token AND // AND
102 %token OR // OR
103 %token NOT //!
104 %token DOT //.
105 %token COMMA //,
106 %token PROP_OPEN // $(
107 %token ITEM_OPEN // @(
108 %token METADATA_OPEN // %(
109 %token PAREN_OPEN // (
110 %token PAREN_CLOSE // )
111 %token BRACE_OPEN // [
112 %token BRACE_CLOSE // ]
113 %token COLON2 // ::
114 %token ARROW // ->
115 %token NAME
116 %token ERROR
117
118 %start ExpressionList
119
120 %%
121
122 ExpressionList
123         : /* empty */
124           { $$ = new ExpressionList (); }
125         | ExpressionList Expression
126           { $$ = ((ExpressionList) $1).Add ((Expression) $2); }
127         ;
128
129 Expression
130         : LogicalExpression
131         ;
132
133 LogicalExpression
134         : ComparisonExpression
135         | LogicalExpression AND LogicalExpression
136           { $$ = Binary (Operator.And, $1, $3); }
137         | LogicalExpression OR LogicalExpression
138           { $$ = Binary (Operator.Or, $1, $3); }
139         ;
140
141 ComparisonExpression
142         : UnaryExpression
143         | UnaryExpression EQ UnaryExpression
144           { $$ = Binary (Operator.EQ, $1, $3); }
145         | UnaryExpression NE UnaryExpression
146           { $$ = Binary (Operator.NE, $1, $3); }
147         | UnaryExpression GT UnaryExpression
148           { $$ = Binary (Operator.GT, $1, $3); }
149         | UnaryExpression GE UnaryExpression
150           { $$ = Binary (Operator.GE, $1, $3); }
151         | UnaryExpression LT UnaryExpression
152           { $$ = Binary (Operator.LT, $1, $3); }
153         | UnaryExpression LE UnaryExpression
154           { $$ = Binary (Operator.LE, $1, $3); }
155         ;
156
157 UnaryExpression
158         : PrimaryExpression
159         | NOT UnaryExpression
160           { $$ = new NotExpression () { Negated = (Expression) $2, Location = (ILocation) $1 }; }
161         ;
162
163 PrimaryExpression
164         : BooleanLiteral
165         | StringLiteral
166         | UnaryExpression
167         | PropertyAccessExpression
168         | ItemAccessExpression
169         | MetadataAccessExpression
170         | RawStringLiteralOrFunction
171         | ParenthesizedExpression
172         ;
173         
174 BooleanLiteral
175         : TRUE_LITERAL
176           { $$ = new BooleanLiteral () { Value = true, Location = (ILocation) $1 }; }
177         | FALSE_LITERAL
178           { $$ = new BooleanLiteral () { Value = false, Location = (ILocation) $1 }; }
179         ;
180
181 PropertyAccessExpression
182         : PROP_OPEN PropertyAccess PAREN_CLOSE
183           { $$ = new PropertyAccessExpression () { Access = (PropertyAccess) $2, Location = (ILocation) $1 }; }
184         ;
185
186 PropertyAccess
187         : NAME
188           { $$ = new PropertyAccess () { Name = (NameToken) $1, TargetType = PropertyTargetType.Object, Location = (NameToken) $1 }; }
189         | Expression DOT NAME
190           { $$ = new PropertyAccess () { Name = (NameToken) $3, Target = (Expression) $1, TargetType = PropertyTargetType.Object, Location = (ILocation) $1 }; }
191         | BRACE_OPEN QualifiedNameExpression BRACE_CLOSE COLON2 NAME
192           { $$ = new PropertyAccess () { Name = (NameToken) $5, Target = (Expression) $2, TargetType = PropertyTargetType.Type, Location = (ILocation) $1 }; }
193         | BRACE_OPEN QualifiedNameExpression BRACE_CLOSE COLON2 NAME PAREN_OPEN FunctionCallArguments PAREN_CLOSE
194           { $$ = new PropertyAccess () { Name = (NameToken) $5, Target = (Expression) $2, TargetType = PropertyTargetType.Type, Arguments = (ExpressionList) $7, Location = (ILocation) $1 }; }
195         ;
196
197 QualifiedNameExpression
198         : QualifiedName
199           { $$ = new StringLiteral () { Value = (NameToken) $1, Location = (ILocation) $1 }; }
200         ;
201
202 QualifiedName
203         : NAME
204         | QualifiedName DOT NAME
205           { $$ = new NameToken () { Name = ((NameToken) $1).Name + "." + ((NameToken) $3).Name, Column = ((ILocation) $1).Column }; }
206         ;
207
208 ItemAccessExpression
209         : ITEM_OPEN ItemApplication PAREN_CLOSE
210           { $$ = new ItemAccessExpression () { Application = (ItemApplication) $2, Location = (ILocation) $1 }; }
211         ;
212
213 // looking a bit messy, but gives different location
214 ItemApplication
215         : NAME
216           { $$ = new ItemApplication () { Name = (NameToken) $1, Location = (ILocation) $1 }; }
217         | NAME ARROW ExpressionList
218           { $$ = new ItemApplication () { Name = (NameToken) $1, Expressions = (ExpressionList) $3, Location = (ILocation) $1 }; }
219         ;
220
221 MetadataAccessExpression
222         : METADATA_OPEN MetadataAccess PAREN_CLOSE
223           { $$ = new MetadataAccessExpression () { Access = (MetadataAccess) $2, Location = (ILocation) $1 }; }
224         ;
225
226 // looking a bit messy, but gives different location
227 MetadataAccess
228         : NAME
229           { $$ = new MetadataAccess () { Metadata = (NameToken) $1, Location = (ILocation) $1 }; }
230         | NAME DOT NAME
231           { $$ = new MetadataAccess () { ItemType = (NameToken) $1, Metadata = (NameToken) $3, Location = (ILocation) $1 }; }
232         ;
233
234 StringLiteral
235         : STRING_LITERAL
236           { $$ = new StringLiteral () { Value = (NameToken) $1, Location = (ILocation) $1 }; }
237         ;
238
239 RawStringLiteralOrFunction
240         : NAME
241           { $$ = new RawStringLiteral () { Value = (NameToken) $1, Location = (ILocation) $1 }; }
242         | NAME PAREN_OPEN PAREN_CLOSE
243           { $$ = new FunctionCallExpression () { Name = (NameToken) $1, Arguments = new ExpressionList (), Location = (ILocation) $1 }; }
244         | NAME PAREN_OPEN FunctionCallArguments PAREN_CLOSE
245           { $$ = new FunctionCallExpression () { Name = (NameToken) $1, Arguments = (ExpressionList) $3, Location = (ILocation) $1 }; }
246         ;
247
248 FunctionCallArguments
249         : /* empty */
250           { $$ = new ExpressionList (); }
251         | Expression
252           { $$ = new ExpressionList ().Add ((Expression) $1); }
253         | FunctionCallArguments COMMA Expression
254           { $$ = ((ExpressionList) $1).Add ((Expression) $3); }
255         ;
256
257 ParenthesizedExpression
258         : PAREN_OPEN Expression PAREN_CLOSE
259           { $$ = (Expression) $2; }
260         ;
261
262 %%
263
264         }