public virtual object VisitPredefinedTypeReference(PredefinedTypeNode predefinedTypeNode, object data) { stackMap.Push(predefinedTypeNode); if (predefinedTypeNode.Generic != null) { predefinedTypeNode.Generic.AcceptVisitor(this, data); } stackMap.Pop(); return(null); }
/// <summary> /// this method parse the next token. /// </summary> /// <param name="checkIsType"> /// if set to <c>true</c>, it will check that the identifier is a type. If it is a type, it converts it /// to a TypeNode. /// if set to <c>false</c>, it will not check that the identifier is a type. /// /// Set it to <c>false</c> in the case of a type declaration while your are parsing the type's name /// /// </param> /// <returns> /// Generally it returns identifier expression /// But in some cases ,it is possible to resolve the kind the expression, /// so it might returns a TypeNode object. /// /// For exemple in this case : System.Collections.Generic.List<int> /// /// The first identifiers are really identifier. /// And the last identifier is a type, and now that because of the generic declaration /// /// in the next case : /// /// System.Collections.ArrayList /// /// All are returned as Identifier, because in the first stage of the parser, /// we are not able to pronostic what is it the kind of the expression. The ArrayList type will /// be resolved in another parser stage /// </returns> private ExpressionNode ParseIdentifierOrKeyword(bool checkIsType, bool consumeTypeParameter, bool allowTypeParameterAttributes, bool inDeclaration) { ExpressionNode result = null; switch (curtok.ID) { case TokenID.Ident: if (Lexer.IsKeyWord(curtok.ID)) { // in this case a key word is used like a variable name. result = new IdentifierExpression(curtok.ID.ToString().ToLower(), curtok); } else { result = new IdentifierExpression(strings[curtok.Data], curtok); } Advance(); while (curtok.ID == TokenID.BSlash) { Advance(); string c = char.ConvertFromUtf32( int.Parse(strings[curtok.Data].TrimStart('\\').TrimStart('u'), NumberStyles.HexNumber ) ); ((IdentifierExpression)result).Identifier += c ; Advance(); } break; case TokenID.Bool: case TokenID.Byte: case TokenID.Char: case TokenID.Decimal: case TokenID.Double: case TokenID.Float: case TokenID.Int: case TokenID.Long: case TokenID.Object: case TokenID.SByte: case TokenID.Short: case TokenID.String: case TokenID.UInt: case TokenID.ULong: case TokenID.UShort: case TokenID.Void: result = new PredefinedTypeNode(curtok.ID, curtok); Advance(); break; case TokenID.If: case TokenID.Else: case TokenID.This: case TokenID.Base: string predef = Enum.GetName(TokenID.Invalid.GetType(), curtok.ID).ToLower(); result = new IdentifierExpression(predef, curtok); ((IdentifierExpression)result).StartingPredefinedType = curtok.ID; Advance(); break; default: if (Lexer.IsKeyWord(curtok.ID)) { // in this case a key word is used like a variable name. goto case TokenID.Ident; } else { RecoverFromError(TokenID.Ident); } break; } if (checkIsType) { result = CheckIdentifierIsType(result, consumeTypeParameter, allowTypeParameterAttributes, inDeclaration); } //check if it is an array access // TODO return result; }
// statements private StatementNode ParseStatement() { // label ident : colon // localDecl type : ident // block LCurly // empty Semi // expression // -invoke pexpr : LParen // -objCre new : type // -assign uexpr : assignOp // -postInc pexpr : ++ // -postDec pexpr : -- // -preInc ++ : uexpr // -preDec -- : uexpr // // selection if : LParen // switch : LParen // // iteration while : LParen // do : LParen // for : LParen // foreach : LParen // // jump break : Semi // continue: Semi // goto : ident | case | default // return : expr // throw : expr // // try try : block // checked checked : block // unchecked unchecked : block // lock lock : LParen // using using : LParen StatementNode node; mayBeLocalDecl = false; switch (curtok.ID) { case TokenID.LCurly: // block BlockStatement newBlock = new BlockStatement(isUnsafe > 0, curtok); newBlock.IsUnsafe = isUnsafe > 0; node = newBlock; ParseBlock(newBlock); break; case TokenID.Semi: // empty statement node = new StatementNode(curtok); Advance(); // over semi break; case TokenID.If: // If statement node = ParseIf(); break; case TokenID.Switch: // Switch statement node = ParseSwitch(); break; case TokenID.While: // While statement node = ParseWhile(); break; case TokenID.Do: // Do statement node = ParseDo(); break; case TokenID.For: // For statement node = ParseFor(); break; case TokenID.Foreach: // Foreach statement node = ParseForEach(); break; case TokenID.Break: // Break statement node = ParseBreak(); break; case TokenID.Continue: // Continue statement node = ParseContinue(); break; case TokenID.Goto: // Goto statement node = ParseGoto(); break; case TokenID.Return: // Return statement node = ParseReturn(); break; case TokenID.Throw: // Throw statement node = ParseThrow(); break; case TokenID.Try: // Try statement node = ParseTry(); break; case TokenID.Checked: // Checked statement node = ParseChecked(); break; case TokenID.Unchecked: // Unchecked statement node = ParseUnchecked(); break; case TokenID.Lock: // Lock statement node = ParseLock(); break; case TokenID.Using: // Using statement node = ParseUsing(); break; case TokenID.Const: node = null; isLocalConst = true; Advance(); // over const break; case TokenID.StringLiteral: case TokenID.HexLiteral: case TokenID.IntLiteral: case TokenID.UIntLiteral: case TokenID.LongLiteral: case TokenID.ULongLiteral: case TokenID.True: case TokenID.False: case TokenID.Null: case TokenID.LParen: case TokenID.DecimalLiteral: case TokenID.RealLiteral: case TokenID.CharLiteral: case TokenID.PlusPlus: // PreInc statement case TokenID.MinusMinus:// PreDec statement case TokenID.This: case TokenID.Base: case TokenID.New: // creation statement node = new ExpressionStatement(ParseExpression()); AssertAndAdvance(TokenID.Semi); break; case TokenID.Void: // TODO: Special case void case TokenID.Bool: case TokenID.Byte: case TokenID.Char: case TokenID.Decimal: case TokenID.Double: case TokenID.Float: case TokenID.Int: case TokenID.Long: case TokenID.Object: case TokenID.SByte: case TokenID.Short: case TokenID.String: case TokenID.UInt: case TokenID.ULong: case TokenID.UShort: { TypeNode type = new PredefinedTypeNode(curtok.ID, curtok); Advance(); bool mustBeDecl = false; if (curtok.ID == TokenID.Question) { Advance(); type.IsNullableType = true; mustBeDecl = true; } else if (curtok.ID == TokenID.Star) { do { Advance(); type = new TypePointerNode(type); } while (curtok.ID == TokenID.Star); mustBeDecl = true; } if (curtok.ID == TokenID.LBracket) { do { Advance(); // over lbracket int commaCount = 0; while (curtok.ID == TokenID.Comma) { Advance(); commaCount++; } type.RankSpecifiers.Add(commaCount); AssertAndAdvance(TokenID.RBracket); } while (curtok.ID == TokenID.LBracket); mustBeDecl = true; } if (curtok.ID == TokenID.Ident) { node = ParseLocalDeclarationStatement(type); } else if (mustBeDecl) { RecoverFromError(TokenID.Ident); node = new StatementNode(curtok); } else { ExpressionNode expr = ParseSubexpression(1, type); if (!(expr is InvocationExpression)) { ReportError("Statement must be an invocation", expr.RelatedToken); } node = new ExpressionStatement(expr); } AssertAndAdvance(TokenID.Semi); break; } case TokenID.Ident: { if (strings[curtok.Data] == "yield") { node = ParseYieldStatement(); break; } ExpressionNode expr = ParseExpressionOrType(true); if (expr is IdentifierExpression && curtok.ID == TokenID.Colon) { Advance(); // advance over colon LabeledStatement lsnode = new LabeledStatement(curtok); lsnode.Name = (IdentifierExpression)expr; lsnode.Statement = ParseStatement(); node = lsnode; } else { if (expr is TypeNode) node = ParseLocalDeclarationStatement((IType)expr); else node = new ExpressionStatement(expr); AssertAndAdvance(TokenID.Semi); } /* ExpressionNode expr = ParseIdentifierOrKeyword(false, true, false, false); IdentifierExpression idExpr = expr as IdentifierExpression; if(idExpr != null && curtok.ID == TokenID.Colon) { Advance(); // advance over colon LabeledStatement lsnode = new LabeledStatement(curtok); lsnode.Name = idExpr; lsnode.Statement = ParseStatement(); node = lsnode; } else { mayBeLocalDecl = true; if(curtok.ID == TokenID.ColonColon) { Advance(); if(curtok.ID != TokenID.Ident) { RecoverFromError(TokenID.Ident); node = null; break; } expr = new MemberAccessExpression(expr, new IdentifierExpression(strings[curtok.Data], curtok), TokenID.ColonColon); Advance(); // over ident } while(curtok.ID == TokenID.Dot) { Advance(); if(curtok.ID != TokenID.Ident) { RecoverFromError(TokenID.Ident); node = null; break; } expr = new MemberAccessExpression(expr, new IdentifierExpression(strings[curtok.Data], curtok), TokenID.Dot); Advance(); // over ident } if(ParsePossibleTypeParameterNode(false, false, false)) { expr = new TypeNode(expr); ApplyTypeParameters((TypeNode) expr); } if(curtok.ID == TokenID.LBracket) { Advance(); if(curtok.ID == TokenID.Comma || curtok.ID == TokenID.RBracket) { TypeNode typeNode = expr as TypeNode; if(typeNode == null) expr = typeNode = new TypeNode(expr); while(true) { int numCommas = 0; while(curtok.ID == TokenID.Comma) { Advance(); numCommas++; } AssertAndAdvance(TokenID.RBracket); typeNode.RankSpecifiers.Add(numCommas); if(curtok.ID != TokenID.LBracket) break; Advance(); } } else { ExpressionList exprList = ParseExpressionList(); expr = new ElementAccessExpression(expr, exprList); AssertAndAdvance(TokenID.RBracket); } } if(curtok.ID == TokenID.Question) { Advance(); TypeNode typeNode = expr as TypeNode; if(typeNode == null) expr = typeNode = new TypeNode(expr); typeNode.IsNullableType = true; } else { while(curtok.ID == TokenID.Star) { Advance(); expr = new TypePointerNode(expr); } }*/ // expr = ParseSubexpression(PRECEDENCE_PRIMARY, expr); /* exprStack.Push(expr); ParseContinuingPrimary(); expr = exprStack.Pop();*/ /* if((expr is IdentifierExpression || expr is MemberAccessExpression || expr is TypeNode) && (curtok.ID == TokenID.Ident || curtok.ID == TokenID.Star || curtok.ID == TokenID.Question)) { node = ParseLocalDeclarationStatement((IType) expr); } else node = new ExpressionStatement(ParseSubexpression(1, expr)); AssertAndAdvance(TokenID.Semi); }*/ break; } case TokenID.Unsafe: // preprocessor directives node = ParseUnsafeCode(); break; case TokenID.Fixed: // preprocessor directives node = ParseFixedStatement(); break; case TokenID.Star: // dereference variable // introduced because of the mono file test-406.cs //private static uint DoOp2 (uint *u) { // *(u) += 100; // return *u; //} node = new ExpressionStatement(ParseExpression()); AssertAndAdvance(TokenID.Semi); break; case TokenID.SingleComment: case TokenID.MultiComment: case TokenID.DocComment: node = new CommentStatement(curtok, strings[curtok.Data], curtok.ID != TokenID.SingleComment); Advance(); // over comment token break; default: { Console.WriteLine("Unhandled case in statement parsing: \"" + curtok.ID + "\" in line: " + lineCount); // this is almost always an expression ExpressionStatement dnode = new ExpressionStatement(ParseExpression()); node = dnode; if (curtok.ID == TokenID.Semi) { Advance(); } break; } } return node; }
private ExpressionNode ParsePrimaryExpression() { Token tok = curtok; ExpressionNode result; // TODO: handle error cases (result = null) switch (curtok.ID) { #region Literals case TokenID.Null: result = new NullPrimitive(curtok); Advance(); break; case TokenID.True: result = new BooleanPrimitive(true, curtok); Advance(); break; case TokenID.False: result = new BooleanPrimitive(false, curtok); Advance(); break; case TokenID.IntLiteral: result = new IntegralPrimitive(strings[curtok.Data], IntegralType.Int, curtok); Advance(); break; case TokenID.UIntLiteral: result = new IntegralPrimitive(strings[curtok.Data], IntegralType.UInt, curtok); Advance(); break; case TokenID.LongLiteral: result = new IntegralPrimitive(strings[curtok.Data], IntegralType.Long, curtok); Advance(); break; case TokenID.ULongLiteral: result = new IntegralPrimitive(strings[curtok.Data], IntegralType.ULong, curtok); Advance(); break; case TokenID.RealLiteral: result = new RealPrimitive(strings[curtok.Data], curtok); Advance(); break; case TokenID.CharLiteral: result = new CharPrimitive(strings[curtok.Data], curtok); Advance(); break; case TokenID.StringLiteral: result = new StringPrimitive(strings[curtok.Data], curtok); Advance(); break; #endregion #region Predefined Types case TokenID.Bool: case TokenID.Byte: case TokenID.Char: case TokenID.Decimal: case TokenID.Double: case TokenID.Float: case TokenID.Int: case TokenID.Long: case TokenID.Object: case TokenID.SByte: case TokenID.Short: case TokenID.String: case TokenID.UInt: case TokenID.ULong: case TokenID.UShort: result = new PredefinedTypeNode(tok.ID, tok); Advance(); result = ParseMemberAccess(result); break; #endregion #region Keywords case TokenID.This: { Advance(); IdentifierExpression idExpr = new IdentifierExpression("this", tok); idExpr.StartingPredefinedType = tok.ID; result = idExpr; break; } case TokenID.Base: Advance(); // over base if (curtok.ID == TokenID.LBracket) // base indexer expression { Advance(); result = new ElementAccessExpression(new IdentifierExpression("base", tok), ParseExpressionList()); AssertAndAdvance(TokenID.RBracket); break; } if (curtok.ID != TokenID.Dot) { RecoverFromError(TokenID.Dot, TokenID.LBracket); result = null; break; } // base access expression Advance(); // advance over dot result = new BaseAccessExpression(ParseMember(false)); break; case TokenID.Checked: Advance(); AssertAndAdvance(TokenID.LParen); result = new CheckedExpression(ParseExpression()); AssertAndAdvance(TokenID.RParen); break; case TokenID.Unchecked: Advance(); AssertAndAdvance(TokenID.LParen); result = new UncheckedExpression(ParseExpression()); AssertAndAdvance(TokenID.RParen); break; case TokenID.Default: Advance(); AssertAndAdvance(TokenID.LParen); result = new DefaultConstantExpression(ParseType(false)); AssertAndAdvance(TokenID.RParen); break; case TokenID.New: Advance(); isNewStatement = true; IType newType = ParseType(false); //ApplyTypeParameters(newType); -> not sure, but a type pointer can not be generic! if (curtok.ID == TokenID.LParen) { Advance(); result = new ObjectCreationExpression(newType, ParseArgumentList(), tok); AssertAndAdvance(TokenID.RParen); } else if (curtok.ID == TokenID.LBracket) { result = ParseArrayCreation(newType); } else { RecoverFromError(TokenID.LParen, TokenID.LBracket); result = null; } isNewStatement = false; break; case TokenID.Typeof: Advance(); AssertAndAdvance(TokenID.LParen); result = new TypeOfExpression(ParseType(false)); CheckRankSpecifier(result); AssertAndAdvance(TokenID.RParen); break; case TokenID.Sizeof: Advance(); AssertAndAdvance(TokenID.LParen); result = new SizeOfExpression(ParseType(false)); AssertAndAdvance(TokenID.RParen); break; case TokenID.Delegate: //anonymous method Advance(); result = ParseAnonymousMethod(); break; #endregion Keywords case TokenID.Ident: result = ParseIdentifierOrKeyword(false, false, false, false, false); if (curtok.ID == TokenID.ColonColon) { // id :: id type-parameter-list_opt . id type-parameter-list_opt QualifiedIdentifierExpression qualID = new QualifiedIdentifierExpression(curtok); // TODO: Replace by QualifiedAliasMember instance qualID.IsNamespaceAliasQualifier = true; qualID.Expressions.Add(result); Advance(); // over ColonColon qualID.Expressions.Add(ParseMember(false)); result = ParseMemberAccess(qualID); } else if (ParsePossibleTypeParameterNode(false, false, false, false)) { result = new TypeNode(result); ApplyTypeParameters((TypeNode)result); } break; case TokenID.LParen: Advance(); result = ParseCastOrGroup(); break; default: RecoverFromError("Unexpected token in primary expression"); return null; // TODO: Invalid expression } return result; }
public virtual object VisitPredefinedTypeReference(PredefinedTypeNode predefinedTypeNode, object data) { stackMap.Push(predefinedTypeNode); if (predefinedTypeNode.Generic != null) { predefinedTypeNode.Generic.AcceptVisitor(this, data); } stackMap.Pop(); return null; }