2 // ExpressionParser.jay
5 // Atsushi Enomoto (atsushi@xamarin.com)
7 // Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
32 using Microsoft.Build.Evaluation;
33 using Microsoft.Build.Exceptions;
34 using Microsoft.Build.Framework;
38 Pseudo formal syntax for .NET 4.0 expression:
40 Condition = Expression
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
59 "$(" PropertyApplication ")"
61 "@(" ItemApplication ")"
62 MetadataBatchingExpression
63 "%(" MetadataBatchingApplication ")"
64 StringLiteralOrFunction
65 StringLiteralOrFunctionName ( "(" FunctionArguments ")" )?
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.
72 namespace Microsoft.Build.Internal.Expressions
74 class ExpressionParser
76 static readonly int yacc_verbose_flag = Environment.GetEnvironmentVariable ("MONO_MSBUILD_PARSER_DEBUG") == "1" ? 1 : 0;
78 object debug_obj = yacc_verbose_flag == 0 ? null : new yydebug.yyDebugSimple ();
80 public ExpressionList Parse (string source, ExpressionValidationType validationType)
82 var tokenizer = new ExpressionTokenizer (source, validationType);
83 return (ExpressionList) yyparse (tokenizer, debug_obj);
86 BinaryExpression Binary (Operator op, object left, object right)
88 return new BinaryExpression () { Operator = op, Left = (Expression) left, Right = (Expression) right, Location = (ILocation) left };
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 // ]
118 %start ExpressionList
124 { $$ = new ExpressionList (); }
125 | ExpressionList Expression
126 { $$ = ((ExpressionList) $1).Add ((Expression) $2); }
134 : ComparisonExpression
135 | LogicalExpression AND LogicalExpression
136 { $$ = Binary (Operator.And, $1, $3); }
137 | LogicalExpression OR LogicalExpression
138 { $$ = Binary (Operator.Or, $1, $3); }
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); }
159 | NOT UnaryExpression
160 { $$ = new NotExpression () { Negated = (Expression) $2, Location = (ILocation) $1 }; }
167 | PropertyAccessExpression
168 | ItemAccessExpression
169 | MetadataAccessExpression
170 | RawStringLiteralOrFunction
171 | ParenthesizedExpression
176 { $$ = new BooleanLiteral () { Value = true, Location = (ILocation) $1 }; }
178 { $$ = new BooleanLiteral () { Value = false, Location = (ILocation) $1 }; }
181 PropertyAccessExpression
182 : PROP_OPEN PropertyAccess PAREN_CLOSE
183 { $$ = new PropertyAccessExpression () { Access = (PropertyAccess) $2, Location = (ILocation) $1 }; }
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 }; }
197 QualifiedNameExpression
199 { $$ = new StringLiteral () { Value = (NameToken) $1, Location = (ILocation) $1 }; }
204 | QualifiedName DOT NAME
205 { $$ = new NameToken () { Name = ((NameToken) $1).Name + "." + ((NameToken) $3).Name, Column = ((ILocation) $1).Column }; }
209 : ITEM_OPEN ItemApplication PAREN_CLOSE
210 { $$ = new ItemAccessExpression () { Application = (ItemApplication) $2, Location = (ILocation) $1 }; }
213 // looking a bit messy, but gives different location
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 }; }
221 MetadataAccessExpression
222 : METADATA_OPEN MetadataAccess PAREN_CLOSE
223 { $$ = new MetadataAccessExpression () { Access = (MetadataAccess) $2, Location = (ILocation) $1 }; }
226 // looking a bit messy, but gives different location
229 { $$ = new MetadataAccess () { Metadata = (NameToken) $1, Location = (ILocation) $1 }; }
231 { $$ = new MetadataAccess () { ItemType = (NameToken) $1, Metadata = (NameToken) $3, Location = (ILocation) $1 }; }
236 { $$ = new StringLiteral () { Value = (NameToken) $1, Location = (ILocation) $1 }; }
239 RawStringLiteralOrFunction
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 }; }
248 FunctionCallArguments
250 { $$ = new ExpressionList (); }
252 { $$ = new ExpressionList ().Add ((Expression) $1); }
253 | FunctionCallArguments COMMA Expression
254 { $$ = ((ExpressionList) $1).Add ((Expression) $3); }
257 ParenthesizedExpression
258 : PAREN_OPEN Expression PAREN_CLOSE
259 { $$ = (Expression) $2; }