@@ -81,7 +81,7 @@ private Expression ParseExpressionSegment()
8181 {
8282 // The following methods respect the operator precedence as defined in
8383 // MSDN C# "Operator precedence and associativity"
84- // http ://msdn .microsoft.com/en-us/library/aa691323(v=vs.71).aspx
84+ // https ://docs .microsoft.com/en-us/dotnet/csharp/language-reference/operators/
8585
8686 return ParseAssignement ( ) ;
8787 }
@@ -107,8 +107,14 @@ private Expression ParseAssignement()
107107 private Expression ParseConditional ( )
108108 {
109109 var errorPos = _token . pos ;
110- var expr = ParseLogicalOr ( ) ;
111- if ( _token . id == TokenId . Question )
110+ var expr = ParseConditionalOr ( ) ;
111+ if ( _token . id == TokenId . QuestionQuestion )
112+ {
113+ NextToken ( ) ;
114+ var exprRight = ParseExpressionSegment ( ) ;
115+ expr = GenerateConditional ( GenerateEqual ( expr , ParserConstants . NullLiteralExpression ) , exprRight , expr , errorPos ) ;
116+ }
117+ else if ( _token . id == TokenId . Question )
112118 {
113119 NextToken ( ) ;
114120 var expr1 = ParseExpressionSegment ( ) ;
@@ -121,29 +127,71 @@ private Expression ParseConditional()
121127 }
122128
123129 // || operator
124- private Expression ParseLogicalOr ( )
130+ private Expression ParseConditionalOr ( )
125131 {
126- var left = ParseLogicalAnd ( ) ;
132+ var left = ParseConditionalAnd ( ) ;
127133 while ( _token . id == TokenId . DoubleBar )
128134 {
129135 NextToken ( ) ;
130- var right = ParseLogicalAnd ( ) ;
136+ var right = ParseConditionalAnd ( ) ;
131137 CheckAndPromoteOperands ( typeof ( ParseSignatures . ILogicalSignatures ) , ref left , ref right ) ;
132138 left = Expression . OrElse ( left , right ) ;
133139 }
134140 return left ;
135141 }
136142
137143 // && operator
144+ private Expression ParseConditionalAnd ( )
145+ {
146+ var left = ParseLogicalOr ( ) ;
147+ while ( _token . id == TokenId . DoubleAmphersand )
148+ {
149+ NextToken ( ) ;
150+ var right = ParseLogicalOr ( ) ;
151+ CheckAndPromoteOperands ( typeof ( ParseSignatures . ILogicalSignatures ) , ref left , ref right ) ;
152+ left = Expression . AndAlso ( left , right ) ;
153+ }
154+ return left ;
155+ }
156+
157+ // | operator
158+ private Expression ParseLogicalOr ( )
159+ {
160+ var left = ParseLogicalXor ( ) ;
161+ while ( _token . id == TokenId . Bar )
162+ {
163+ NextToken ( ) ;
164+ var right = ParseLogicalXor ( ) ;
165+ CheckAndPromoteOperands ( typeof ( ParseSignatures . ILogicalSignatures ) , ref left , ref right ) ;
166+ left = Expression . Or ( left , right ) ;
167+ }
168+ return left ;
169+ }
170+
171+ // ^ operator
172+ private Expression ParseLogicalXor ( )
173+ {
174+ var left = ParseLogicalAnd ( ) ;
175+ while ( _token . id == TokenId . Caret )
176+ {
177+ NextToken ( ) ;
178+ var right = ParseLogicalAnd ( ) ;
179+ CheckAndPromoteOperands ( typeof ( ParseSignatures . ILogicalSignatures ) , ref left , ref right ) ;
180+ left = Expression . ExclusiveOr ( left , right ) ;
181+ }
182+ return left ;
183+ }
184+
185+ // & operator
138186 private Expression ParseLogicalAnd ( )
139187 {
140188 var left = ParseComparison ( ) ;
141- while ( _token . id == TokenId . DoubleAmphersand )
189+ while ( _token . id == TokenId . Amphersand )
142190 {
143191 NextToken ( ) ;
144192 var right = ParseComparison ( ) ;
145193 CheckAndPromoteOperands ( typeof ( ParseSignatures . ILogicalSignatures ) , ref left , ref right ) ;
146- left = Expression . AndAlso ( left , right ) ;
194+ left = Expression . And ( left , right ) ;
147195 }
148196 return left ;
149197 }
@@ -380,6 +428,11 @@ private Expression ParsePrimary()
380428 NextToken ( ) ;
381429 expr = ParseMemberAccess ( null , expr ) ;
382430 }
431+ else if ( _token . id == TokenId . QuestionDot )
432+ {
433+ NextToken ( ) ;
434+ expr = GenerateConditional ( GenerateEqual ( expr , ParserConstants . NullLiteralExpression ) , ParserConstants . NullLiteralExpression , ParseMemberAccess ( null , expr ) , _token . pos ) ;
435+ }
383436 else if ( _token . id == TokenId . OpenBracket )
384437 {
385438 expr = ParseElementAccess ( expr ) ;
@@ -1089,10 +1142,10 @@ private static string GetTypeName(Type type)
10891142 return s ;
10901143 }
10911144
1092- // static bool IsNumericType(Type type)
1093- // {
1094- // return GetNumericTypeKind(type) != 0;
1095- // }
1145+ static bool IsNumericType ( Type type )
1146+ {
1147+ return GetNumericTypeKind ( type ) != 0 ;
1148+ }
10961149
10971150 private static bool IsSignedIntegralType ( Type type )
10981151 {
@@ -1423,7 +1476,7 @@ private static Expression PromoteExpression(Expression expr, Type type, bool exa
14231476 }
14241477 }
14251478
1426- if ( type . IsGenericType )
1479+ if ( type . IsGenericType && ! IsNumericType ( type ) )
14271480 {
14281481 var genericType = FindAssignableGenericType ( expr . Type , type . GetGenericTypeDefinition ( ) ) ;
14291482 if ( genericType != null )
@@ -1604,8 +1657,8 @@ private static bool HasParamsArrayType(ParameterInfo parameterInfo)
16041657 private static Type GetParameterType ( ParameterInfo parameterInfo )
16051658 {
16061659 var isParamsArray = HasParamsArrayType ( parameterInfo ) ;
1607- var type = isParamsArray
1608- ? parameterInfo . ParameterType . GetElementType ( )
1660+ var type = isParamsArray
1661+ ? parameterInfo . ParameterType . GetElementType ( )
16091662 : parameterInfo . ParameterType ;
16101663 return type ;
16111664 }
@@ -1735,7 +1788,7 @@ private static Expression GenerateSubtract(Expression left, Expression right)
17351788
17361789 private static Expression GenerateStringConcat ( Expression left , Expression right )
17371790 {
1738- var concatMethod = typeof ( string ) . GetMethod ( "Concat" , new [ ] { typeof ( object ) , typeof ( object ) } ) ;
1791+ var concatMethod = typeof ( string ) . GetMethod ( "Concat" , new [ ] { typeof ( object ) , typeof ( object ) } ) ;
17391792 if ( concatMethod == null )
17401793 throw new Exception ( "String concat method not found" ) ;
17411794
@@ -1817,7 +1870,7 @@ private void NextToken()
18171870 }
18181871 else
18191872 {
1820- throw CreateParseException ( _parsePosition , ErrorMessages . InvalidCharacter , _parseChar ) ;
1873+ t = TokenId . Amphersand ;
18211874 }
18221875 break ;
18231876 case '(' :
@@ -1919,7 +1972,18 @@ private void NextToken()
19191972 break ;
19201973 case '?' :
19211974 NextChar ( ) ;
1922- t = TokenId . Question ;
1975+ if ( _parseChar == '.' )
1976+ {
1977+ NextChar ( ) ;
1978+ t = TokenId . QuestionDot ;
1979+ } else if ( _parseChar == '?' )
1980+ {
1981+ NextChar ( ) ;
1982+ t = TokenId . QuestionQuestion ;
1983+ } else
1984+ {
1985+ t = TokenId . Question ;
1986+ }
19231987 break ;
19241988 case '[' :
19251989 NextChar ( ) ;
@@ -1977,6 +2041,10 @@ private void NextToken()
19772041
19782042 t = TokenId . CharLiteral ;
19792043 break ;
2044+ case '^' :
2045+ NextChar ( ) ;
2046+ t = TokenId . Caret ;
2047+ break ;
19802048 default :
19812049
19822050 if ( char . IsLetter ( _parseChar ) || _parseChar == '@' || _parseChar == '_' )
0 commit comments