//----------------------------------------------------------------------------- // Parse enum declaration // --> 'enum' id:name '{' enum_decl_list '}' //----------------------------------------------------------------------------- protected EnumDecl ParseEnum(Modifiers modsEnums) { ReadExpectedToken(Token.Type.cEnum); Identifier idName = ReadExpectedIdentifier(); FileRange f2 = this.BeginRange(); ReadExpectedToken(Token.Type.cLCurly); ArrayList a = new ArrayList(); // All enum fields are Static, Public, Literal // and have fieldtype set to type of the enum //Modifiers mods = new Modifiers(Modifiers.EFlags.Public | Modifiers.EFlags.Static); Modifiers mods = new Modifiers(); mods.SetPublic(); mods.SetStatic(); TypeSig tSig = new SimpleTypeSig(new SimpleObjExp(idName)); Identifier idPrev = null; Token t = m_lexer.PeekNextToken(); while(t.TokenType != Token.Type.cRCurly) { // Parse fields Identifier id = ReadExpectedIdentifier(); Exp expInit = null; t = m_lexer.PeekNextToken(); if (t.TokenType == Token.Type.cAssign) { ConsumeNextToken(); expInit = ParseExp(); } else { #if false // If no explicit assignment, then we must create one // first field -> '=0' if (idPrev == null) { expInit = new IntExp(0, id.Location); } // all other fields -> '= <prevfield> + '1' ' else { expInit = new BinaryExp( new SimpleObjExp(idPrev), new IntExp(1, id.Location), BinaryExp.BinaryOp.cAdd); } #endif } //EnumField e = new EnumField(id); FieldDecl e = new FieldDecl(id, tSig, mods, expInit); a.Add(e); // If no comma, then this had better be our last one t = m_lexer.PeekNextToken(); if (t.TokenType != Token.Type.cComma) { break; } ReadExpectedToken(Token.Type.cComma); idPrev = id; t = m_lexer.PeekNextToken(); } // while parsing fields ReadExpectedToken(Token.Type.cRCurly); // Convert array list to EnumField[] FieldDecl [] f = new FieldDecl[a.Count]; for(int i = 0; i < f.Length; i++) f[i] = (FieldDecl) a[i]; EnumDecl node = new EnumDecl(idName, f, modsEnums); node.SetLocation(this.EndRange(f2)); return node; }
//----------------------------------------------------------------------------- // Parse a comma separated list of identifiers // expect at least 1 entry //----------------------------------------------------------------------------- protected TypeSig[] ParseIdNameList() { ArrayList a = new ArrayList(); Token t; while(true) { Exp o = ParseDottedIdList(); a.Add(o); t = m_lexer.PeekNextToken(); if (t.TokenType == Token.Type.cComma) { ConsumeNextToken(); continue; } break; } TypeSig[] olist = new TypeSig[a.Count]; for(int i = 0; i < a.Count; i++) { olist[i] = new SimpleTypeSig((Exp) a[i]); } return olist; }
//----------------------------------------------------------------------------- // Parse a Type Sig // // ** rules ** // TypeSig -> id ('.' id)* '[ ','* ]'* //----------------------------------------------------------------------------- protected NonRefTypeSig ParseTypeSig() { // Currently, we implement this by parsing ObjExpressions. That's easier // for us, but may let us parse illegal things. That's ok. The TypeSig // container class along with semantic checking will still give us the // expected error control. NonRefTypeSig sig = null; Identifier stId = ReadExpectedIdentifier(); Exp o = new SimpleObjExp(stId); Token t = m_lexer.PeekNextToken(); while (t.TokenType == Token.Type.cDot) { ConsumeNextToken(); stId = ReadExpectedIdentifier(); o = new DotObjExp(o, stId); t = m_lexer.PeekNextToken(); } sig = new SimpleTypeSig(o); // Check for arrays while (t.TokenType == Token.Type.cLRSquare) { sig = new ArrayTypeSig(sig, 1); ConsumeNextToken(); t = m_lexer.PeekNextToken(); } return sig; }
//----------------------------------------------------------------------------- // Parse a new Expression (either array or non-array) // -> 'new' id_list '(' exp, exp ... ')' // // -> 'new' id_list '[x]' '[]'* array_init? // -> 'new' id_list '[]'* array_init // // array_init-> '{' exp, exp, exp, ...'}' //----------------------------------------------------------------------------- protected Exp ParseNewExp() { ReadExpectedToken(Token.Type.cNew); // A typesig would allow [] to be part of the type // An id_list doesn't. Exp oe = ParseDottedIdList(); SimpleTypeSig type = new SimpleTypeSig(oe); Token t2 = m_lexer.PeekNextToken(); // If next is a '(', then this is a ctor call (and not an array) if (t2.TokenType == Token.Type.cLParen) { Exp [] eList = ParseExpList(); Exp e = new NewObjExp(type, eList); return e; } // Array case if (t2.TokenType == Token.Type.cLRSquare || t2.TokenType == Token.Type.cLSquare) { ArrayTypeSig typeArray = null; ArrayInitializer init = null; // dynamic size explicitly in rank specifier // -> 'new' id_list '[x]' '[]'* array_init? if (t2.TokenType == Token.Type.cLSquare) { Exp [] eList = ParseExpList(Token.Type.cLSquare, Token.Type.cRSquare); // includes [ and ] int dim = eList.Length; NonRefTypeSig s = ParseOptionalArrayDecl(type); typeArray = new ArrayTypeSig(s, dim); if (m_lexer.PeekNextToken().TokenType == Token.Type.cLCurly) { init = this.ParseArrayInitList(); } Exp e = new NewArrayObjExp(typeArray,eList,init); return e; } // static size implicitly from array_initializer // -> 'new' id_list '[]'* array_init else if (t2.TokenType == Token.Type.cLRSquare) { NonRefTypeSig t = ParseOptionalArrayDecl(type); typeArray = t.AsArraySig; init = this.ParseArrayInitList(); Exp e = new NewArrayObjExp(typeArray,init); return e; } } ThrowError(E_UnexpectedToken(t2)); return null; }
//----------------------------------------------------------------------------- // E -> E . i // E -> E . i (...) // E -> E [ E] //----------------------------------------------------------------------------- protected Exp ParsePrimaryExp() { Exp eFinal = ParseExpAtom(); // Now, since ObjExp are left-linear, we can actually parse them recursively // We parsed the base case, so we just keep iterating through deciding // which rule to apply. eFinal contains the root of the ast we're building Token t; while(true) { t = m_lexer.PeekNextToken(); // If next char is '.', then we're either doing: // E -> E . i // E -> E . i (...) if (t.TokenType == Token.Type.cDot) { ConsumeNextToken(); // eat the dot Identifier stId = ReadExpectedIdentifier(); Token t2 = m_lexer.PeekNextToken(); // MethodCall - if next character is a '(' // E -> E . i (...) if (t2.TokenType == Token.Type.cLParen) { ArgExp [] arParams = ParseArgList(); eFinal = new MethodCallExp(eFinal, stId, arParams); continue; } // Dot operator - for all other cases // E -> E . i else { eFinal = new DotObjExp(eFinal, stId); continue; } } // If next char is a '[', then this is an array access // E -> E [ E ] else if (t.TokenType == Token.Type.cLSquare) { ConsumeNextToken(); Exp eIdx = ParseExp(); ReadExpectedToken(Token.Type.cRSquare); eFinal = new ArrayAccessExp(eFinal, eIdx); continue; } // If we got to here, then we're done so break out of loop break; } // end while // @hack // Since expressions can be types (ie, that's how we parse a TypeCast) // Check if this is an array type if (t.TokenType == Token.Type.cLRSquare) { NonRefTypeSig sigElemType = new SimpleTypeSig(eFinal); TypeSig tSig = ParseOptionalArrayDecl(sigElemType); return new TempTypeExp(tSig); } return eFinal; }
public CatchHandler( TypeSig type, // type we're catching (must derived from System.Exception) Identifier idName, // optional (can be null) name for local var to store exception BlockStatement stmtBody // handler body (non-null) ) { Debug.Assert(stmtBody != null); // General catch blocks just becomes a System.Exception if (type == null) { m_type = new SimpleTypeSig(new DotObjExp( new SimpleObjExp(new Identifier("System", null)), new Identifier("Exception", null) )); } else { m_type = type; } m_idVarName = idName; m_body = stmtBody; }