//--------------------------------------------------------------------------------------- // ParsePackage // // Package : // 'package' QualifiedIdentifier '{' ClassList '}' // // ClassList : // <empty> | // Class ClassList | // Attributes Class ClassList | // Attributes Enum ClassList //--------------------------------------------------------------------------------------- // Because 'package' is not a reserved word in JS5 we have to deal with an ambiguity // in the grammar. A source sequence like the following // package // x // { } // can be legally parsed in two ways: // Identifier Identifier Block or // Package // we give Package priority in this situation. // Here is how we deal with some possible cases: // 1- ** package <no line break> QualifiedIdentifier ** is parsed unambiguously as a package production regardless of what comes after Identifier // 2- ** package <no line break> NotOneOf(Operator | '[' | '.' | '(' | Identifier) '{' ** is parsed as a package production with an error // 3- ** package <line break> '{' ** is parsed as a package (anonymous) with an error // 4- ** package <line break> Not(Identifier) ** is never parsed as a package private AST ParsePackage(Context packageContext){ GetNextToken(); AST qualid = null; bool gotLineBreak = this.scanner.GotEndOfLine(); // erroneous package production if (JSToken.Identifier != this.currentToken.token){ if (JSScanner.CanParseAsExpression(this.currentToken.token)){ // it's an expression. Report a warning. package and this.currentToken can be an expression (i.e. 'package +') ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); qualid = new Lookup("package", packageContext); // get the member expression qualid = MemberExpression(qualid, null); bool isLeftHandSide; qualid = ParsePostfixExpression(qualid, out isLeftHandSide); qualid = ParseExpression(qualid, false, isLeftHandSide, JSToken.None); return new Expression(qualid.context.Clone(), qualid); }else if (!gotLineBreak){ if (JSToken.Increment == this.currentToken.token || JSToken.Decrement == this.currentToken.token){ // it's a postfix expression. Report a warning ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); bool dummy; qualid = new Lookup("package", packageContext); qualid = ParsePostfixExpression(qualid, out dummy); qualid = ParseExpression(qualid, false, false, JSToken.None); return new Expression(qualid.context.Clone(), qualid); } }else{ // it's an expression. Report a warning which, as a side effect, will make the current token be the next token fetched ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); return new Lookup("package", packageContext); } }else{ // it is an identifier, parse it as a qualified identifier this.errorToken = this.currentToken; // this will make GetNextToken() in ParseQualifiedIdentifier() return this.currentToken qualid = ParseQualifiedIdentifier(JSError.NoIdentifier); } // if we are here we have: // ** package QualifiedIdentifier ** or // ** package SomeNonSenseToken **, that is a token that does not make an expression Context nonSenseToken = null; if (JSToken.LeftCurly != this.currentToken.token && qualid == null){ // we want to peek and see whether the next token is a LeftCurly nonSenseToken = this.currentToken.Clone(); GetNextToken(); } if (JSToken.LeftCurly == this.currentToken.token){ // sounds like a package, possibly with an error. If qualid is not null is actually a good package, otherwise we treat it // as an anonymous package and keep going. if (qualid == null){ if (nonSenseToken == null) nonSenseToken = this.currentToken.Clone(); ReportError(JSError.NoIdentifier, nonSenseToken, true); } }else{ if (qualid == null){ // this is pretty screwy, let's ignore the package keyword for a start ReportError(JSError.SyntaxError, packageContext); if (JSScanner.CanStartStatement(nonSenseToken.token)){ // this is tricky we assign nonSenseToken to this.currentToken and call ParseStatement, because we know it is a statement start token. // The parser should then call GetNextToken() which will return the this.currentToken that is assigned to this.errorToken this.currentToken = nonSenseToken; return ParseStatement(); }else{ //ReportError(JSError.SyntaxError, nonSenseToken); if (JSScanner.CanStartStatement(this.currentToken.token)){ this.errorToken = null; return ParseStatement(); }else{ ReportError(JSError.SyntaxError); SkipTokensAndThrow(); } } }else{ if (gotLineBreak){ // we are here with the following: 'package' <line break> QalifiedIdentifier' however we do not have a left curly. // if the token in our hand can start an expression we go with two expressions, otherwise we accept it as a package //if (JSScanner.CanParseAsExpression(this.currentToken.token)){ ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); Block block = new Block(packageContext.Clone()); block.Append(new Lookup("package", packageContext)); qualid = MemberExpression(qualid, null); bool isLeftHandSide; qualid = ParsePostfixExpression(qualid, out isLeftHandSide); qualid = ParseExpression(qualid, false, true, JSToken.None); block.Append(new Expression(qualid.context.Clone(), qualid)); block.context.UpdateWith(qualid.context); return block; //} } // the package production rule is entered regardless of the presence of a left curly. ReportError(JSError.NoLeftCurly); } } PackageScope pscope = new PackageScope(Globals.ScopeStack.Peek()); Globals.ScopeStack.Push(pscope); //Give declarations a place to go while building AST try{ string name = (qualid != null) ? qualid.ToString() : "anonymous package"; pscope.name = name; packageContext.UpdateWith(this.currentToken); ASTList classList = new ASTList(packageContext); GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_PackageBodyNoSkipTokenSet); try{ while (this.currentToken.token != JSToken.RightCurly){ AST ast = null; try{ switch (this.currentToken.token){ case JSToken.Interface: case JSToken.Class: classList.Append(ParseClass((FieldAttributes)0, false, this.currentToken.Clone(), false, false, null)); break; case JSToken.Enum: classList.Append(ParseEnum((FieldAttributes)0, this.currentToken.Clone(), null)); break; case JSToken.Internal: case JSToken.Public: case JSToken.Static: case JSToken.Private: case JSToken.Protected: case JSToken.Abstract: case JSToken.Final: bool parsedOK; ast = ParseAttributes(null, true, false, out parsedOK); if (parsedOK){ if (ast is Class){ classList.Append(ast); break; } } ReportError(JSError.OnlyClassesAllowed, ast.context.Clone(), true); SkipTokensAndThrow(); break; case JSToken.Identifier: bool bAssign, canBeAttribute = true; ast = ParseUnaryExpression(out bAssign, ref canBeAttribute, false); if (canBeAttribute){ bool parsed; ast = ParseAttributes(ast, true, false, out parsed); if (parsed){ if (ast is Class){ classList.Append(ast); break; } } } ReportError(JSError.OnlyClassesAllowed, ast.context.Clone(), true); SkipTokensAndThrow(); break; case JSToken.EndOfFile: EOFError(JSError.ErrEOF); throw new EndOfFile(); // abort parsing, get back to the main parse routine case JSToken.Semicolon: // ignore any spurious semicolon GetNextToken(); break; case JSToken.Import: // handle common error of using import in package ReportError(JSError.InvalidImport, true); try{ ParseImportStatement(); }catch(RecoveryTokenException){ } break; case JSToken.Package: // handle common error of using package in package Context nestedPackageContext = this.currentToken.Clone(); AST statement = ParsePackage(nestedPackageContext); if (statement is Package) ReportError(JSError.PackageInWrongContext, nestedPackageContext, true); break; default: ReportError(JSError.OnlyClassesAllowed, (ast != null) ? ast.context.Clone() : CurrentPositionContext(), true); SkipTokensAndThrow(); break; } }catch(RecoveryTokenException exc){ if (exc._partiallyComputedNode != null && exc._partiallyComputedNode is Class){ classList.Append((Class)exc._partiallyComputedNode); exc._partiallyComputedNode = null; } if (IndexOfToken(NoSkipTokenSet.s_PackageBodyNoSkipTokenSet, exc) == -1) throw exc; } } }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1){ ReportError(JSError.NoRightCurly, CurrentPositionContext()); exc._partiallyComputedNode = new Package(name, qualid, classList, packageContext); throw exc; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_PackageBodyNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } GetNextToken(); return new Package(name, qualid, classList, packageContext); }finally{ Globals.ScopeStack.Pop(); } }
//--------------------------------------------------------------------------------------- // ParseStaticInitializer // // StaticInitializer : // '{' FunctionBody '}' //--------------------------------------------------------------------------------------- private AST ParseStaticInitializer(Context initContext){ Block body = null; FunctionScope scope = new FunctionScope(Globals.ScopeStack.Peek()); scope.isStatic = true; // make a new state and save the old one ArrayList blockType = this.blockType; this.blockType = new ArrayList(16); SimpleHashtable labelTable = this.labelTable; this.labelTable = new SimpleHashtable(16); this.blockType.Add(BlockType.Block); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); try{ Globals.ScopeStack.Push(scope); //Give declarations a place to go while building AST // parse the block locally to get the exact end of function body = new Block(this.currentToken.Clone()); GetNextToken(); while (JSToken.RightCurly != this.currentToken.token){ try{ body.Append(ParseStatement()); }catch(RecoveryTokenException exc){ if (exc._partiallyComputedNode != null) body.Append(exc._partiallyComputedNode); if (IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exc) == -1) throw exc; } } }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1){ exc._partiallyComputedNode = new StaticInitializer(initContext, body, scope); throw exc; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.blockType = blockType; this.labelTable = labelTable; Globals.ScopeStack.Pop(); } body.context.UpdateWith(this.currentToken); initContext.UpdateWith(this.currentToken); GetNextToken(); return new StaticInitializer(initContext, body, scope); }
//--------------------------------------------------------------------------------------- // ParseClassBody // // ClassBody : // '{' OptionalClassMembers '}' //--------------------------------------------------------------------------------------- Block ParseClassBody(bool isEnum, bool isInterface){ this.blockType.Add(BlockType.Block); Block codeBlock = new Block(this.currentToken.Clone()); try{ GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); JSToken[] noSkip = null; if (isEnum) noSkip = NoSkipTokenSet.s_EnumBodyNoSkipTokenSet; else if (isInterface) noSkip = NoSkipTokenSet.s_InterfaceBodyNoSkipTokenSet; else noSkip = NoSkipTokenSet.s_ClassBodyNoSkipTokenSet; try{ while (JSToken.RightCurly != this.currentToken.token){ if (JSToken.EndOfFile == this.currentToken.token){ ReportError(JSError.NoRightCurly, true); SkipTokensAndThrow(); } this.noSkipTokenSet.Add(noSkip); try{ AST classMember = isEnum ? ParseEnumMember() : ParseClassMember(isInterface); if (classMember != null) codeBlock.Append(classMember); }catch(RecoveryTokenException exc){ if (exc._partiallyComputedNode != null) codeBlock.Append(exc._partiallyComputedNode); if (IndexOfToken(noSkip, exc) == -1){ exc._partiallyComputedNode = null; throw exc; } }finally{ this.noSkipTokenSet.Remove(noSkip); } } }catch(RecoveryTokenException exc){ exc._partiallyComputedNode = codeBlock; throw exc; }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } codeBlock.context.UpdateWith(this.currentToken); GetNextToken(); }finally{ this.blockType.RemoveAt(this.blockType.Count - 1); } return codeBlock; }
private AST ParseFunction(FieldAttributes visibilitySpec, bool inExpression, Context fncCtx, bool isMethod, bool isAbstract, bool isFinal, bool isInterface, CustomAttributeList customAttributes, Call function){ IdentifierLiteral name = null; AST interfaceName = null; ArrayList formalParameters = null; TypeExpression returnType = null; Block body = null; bool isGetter = false; bool isSetter = false; if (function == null){ GetNextToken(); if (isMethod) if (JSToken.Get == this.currentToken.token){ isGetter = true; GetNextToken(); }else if (JSToken.Set == this.currentToken.token){ isSetter = true; GetNextToken(); } // get the function name or make an anonymous function if in expression "position" if (JSToken.Identifier == this.currentToken.token){ name = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); GetNextToken(); if (JSToken.AccessField == this.currentToken.token){ if (isInterface) // "function IBar.foo()" is illegal in an interface declaration ReportError(JSError.SyntaxError, true); GetNextToken(); if (JSToken.Identifier == this.currentToken.token){ interfaceName = new Lookup(name.context); name = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); GetNextToken(); while (JSToken.AccessField == this.currentToken.token){ GetNextToken(); if (JSToken.Identifier == this.currentToken.token){ interfaceName = new Member(interfaceName.context.CombineWith(this.currentToken), interfaceName, new ConstantWrapper(name.ToString(), name.context)); name = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); GetNextToken(); }else ReportError(JSError.NoIdentifier, true); } }else ReportError(JSError.NoIdentifier, true); } }else{ string identifier = JSKeyword.CanBeIdentifier(this.currentToken.token); if (null != identifier){ ForceReportInfo(JSError.KeywordUsedAsIdentifier, isMethod); name = new IdentifierLiteral(identifier, this.currentToken.Clone()); GetNextToken(); }else{ if (!inExpression){ identifier = this.currentToken.GetCode(); ReportError(JSError.NoIdentifier, true); GetNextToken(); }else identifier = ""; name = new IdentifierLiteral(identifier, CurrentPositionContext()); } } }else{ // function was passed in, this is an error condition name = function.GetName(); } // make a new state and save the old one ArrayList blockType = this.blockType; this.blockType = new ArrayList(16); SimpleHashtable labelTable = this.labelTable; this.labelTable = new SimpleHashtable(16); FunctionScope fscope = new FunctionScope(Globals.ScopeStack.Peek(), isMethod); Globals.ScopeStack.Push(fscope); //Give declarations a place to go while building AST try{ formalParameters = new ArrayList(); Context paramArrayContext = null; if (function == null){ // get the formal parameters if (JSToken.LeftParen != this.currentToken.token) ReportError(JSError.NoLeftParen); GetNextToken(); // create the list of arguments and update the context while (JSToken.RightParen != this.currentToken.token){ if (paramArrayContext != null){ ReportError(JSError.ParamListNotLast, paramArrayContext, true); paramArrayContext = null; } String id = null; TypeExpression typeExpr = null; this.noSkipTokenSet.Add(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet); try{ if (JSToken.ParamArray == this.currentToken.token){ paramArrayContext = this.currentToken.Clone(); GetNextToken(); } if (JSToken.Identifier != this.currentToken.token && (id = JSKeyword.CanBeIdentifier(this.currentToken.token)) == null){ if (JSToken.LeftCurly == this.currentToken.token){ ReportError(JSError.NoRightParen); break; }else if (JSToken.Comma == this.currentToken.token){ // We're missing an argument (or previous argument was malformed and // we skipped to the comma.) Keep trying to parse the argument list -- // we will skip the comma below. ReportError(JSError.SyntaxError, true); }else{ ReportError(JSError.SyntaxError, true); SkipTokensAndThrow(); } }else{ if (null == id) id = this.scanner.GetIdentifier(); else ForceReportInfo(JSError.KeywordUsedAsIdentifier); Context paramCtx = this.currentToken.Clone(); GetNextToken(); if (JSToken.Colon == this.currentToken.token){ typeExpr = ParseTypeExpression(); if (null != typeExpr) paramCtx.UpdateWith(typeExpr.context); } CustomAttributeList custAttrs = null; if (paramArrayContext != null){ custAttrs = new CustomAttributeList(paramArrayContext); custAttrs.Append(new CustomAttribute(paramArrayContext, new Lookup("...", paramArrayContext), new ASTList(null))); } formalParameters.Add(new ParameterDeclaration(paramCtx, id, typeExpr, custAttrs)); } // got an arg, it should be either a ',' or ')' if (JSToken.RightParen == this.currentToken.token) break; else if (JSToken.Comma != this.currentToken.token){ // deal with error in some "intelligent" way if (JSToken.LeftCurly == this.currentToken.token){ ReportError(JSError.NoRightParen); break; }else{ if (JSToken.Identifier == this.currentToken.token && typeExpr == null){ // it's possible that the guy was writing the type in C/C++ style (i.e. int x) ReportError(JSError.NoCommaOrTypeDefinitionError); }else ReportError(JSError.NoComma); } } GetNextToken(); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet, exc) == -1) throw exc; }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet); } } fncCtx.UpdateWith(this.currentToken); // if it is a getter/setter must have 0/1 arg only if (isGetter && formalParameters.Count != 0){ ReportError(JSError.BadPropertyDeclaration, true); isGetter = false; }else if (isSetter && formalParameters.Count != 1){ ReportError(JSError.BadPropertyDeclaration, true); isSetter = false; } GetNextToken(); // check the return type if (JSToken.Colon == this.currentToken.token){ if (isSetter) ReportError(JSError.SyntaxError); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); try{ returnType = ParseTypeExpression(); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_StartBlockNoSkipTokenSet, exc) == -1){ exc._partiallyComputedNode = null; throw exc; }else{ if (exc._partiallyComputedNode != null) returnType = (TypeExpression)exc._partiallyComputedNode; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); } if (isSetter) returnType = null; } }else{ // function was passed in, this is an error condition function.GetParameters(formalParameters); } // read the function body of non-abstract functions. if (JSToken.LeftCurly != this.currentToken.token && (isAbstract || (isMethod && GuessIfAbstract()))){ if (!isAbstract){ isAbstract = true; ReportError(JSError.ShouldBeAbstract, fncCtx, true); } body = new Block(this.currentToken.Clone()); }else{ if (JSToken.LeftCurly != this.currentToken.token) ReportError(JSError.NoLeftCurly, true); else if (isAbstract) ReportError(JSError.AbstractWithBody, fncCtx, true); this.blockType.Add(BlockType.Block); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); try{ // parse the block locally to get the exact end of function body = new Block(this.currentToken.Clone()); GetNextToken(); while (JSToken.RightCurly != this.currentToken.token){ try{ body.Append(ParseStatement()); }catch(RecoveryTokenException exc){ if (exc._partiallyComputedNode != null){ body.Append(exc._partiallyComputedNode); } if (IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exc) == -1) throw exc; } } body.context.UpdateWith(this.currentToken); fncCtx.UpdateWith(this.currentToken); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1){ Globals.ScopeStack.Pop(); //Pop current scope so that FunctionDeclaration sees proper scope stack try{ ParameterDeclaration[] foParameters = new ParameterDeclaration[formalParameters.Count]; formalParameters.CopyTo(foParameters); if (inExpression) exc._partiallyComputedNode = new FunctionExpression(fncCtx, name, foParameters, returnType, body, fscope, visibilitySpec); else exc._partiallyComputedNode = new FunctionDeclaration(fncCtx, interfaceName, name, foParameters, returnType, body, fscope, visibilitySpec, isMethod, isGetter, isSetter, isAbstract, isFinal, customAttributes); if (customAttributes != null) customAttributes.SetTarget(exc._partiallyComputedNode); }finally{ Globals.ScopeStack.Push(fscope); //Push it back so that the next finally can pop it } throw exc; } }finally{ this.blockType.RemoveAt(this.blockType.Count - 1); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } GetNextToken(); } }finally{ // restore state this.blockType = blockType; this.labelTable = labelTable; Globals.ScopeStack.Pop(); } ParameterDeclaration[] fParameters = new ParameterDeclaration[formalParameters.Count]; formalParameters.CopyTo(fParameters); AST func; if (inExpression) func = new FunctionExpression(fncCtx, name, fParameters, returnType, body, fscope, visibilitySpec); else func = new FunctionDeclaration(fncCtx, interfaceName, name, fParameters, returnType, body, fscope, visibilitySpec, isMethod, isGetter, isSetter, isAbstract, isFinal, customAttributes); if (customAttributes != null) customAttributes.SetTarget(func); return func; }
//--------------------------------------------------------------------------------------- // ParseExpressionItem // // A VSAITEMTYPE2.EXPRESSION call into here to parse an expression //--------------------------------------------------------------------------------------- internal ScriptBlock ParseExpressionItem(){ try{ Block block = new Block(this.sourceContext.Clone()); GetNextToken(); block.Append(new Expression(this.sourceContext.Clone(), ParseExpression())); return new ScriptBlock(this.sourceContext.Clone(), block); }catch (EndOfFile){ }catch (ScannerException se){ // a scanner exception implies that the end of file has been reached with an error. // Mark the end of file as the error location EOFError(se.m_errorId); } return null; }
//--------------------------------------------------------------------------------------- // ParseSwitchStatement // // SwitchStatement : // 'switch' '(' Expression ')' '{' CaseBlock '}' // // CaseBlock : // CaseList DefaultCaseClause CaseList // // CaseList : // <empty> | // CaseClause CaseList // // CaseClause : // 'case' Expression ':' OptionalStatements // // DefaultCaseClause : // <empty> | // 'default' ':' OptionalStatements //--------------------------------------------------------------------------------------- private AST ParseSwitchStatement(){ Context switchCtx = this.currentToken.Clone(); AST expr = null; ASTList cases = null; this.blockType.Add(BlockType.Switch); try{ // read switch(expr) GetNextToken(); if (JSToken.LeftParen != this.currentToken.token) ReportError(JSError.NoLeftParen); GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet); try{ expr = ParseExpression(); if (JSToken.RightParen != this.currentToken.token){ ReportError(JSError.NoRightParen); } GetNextToken(); if (JSToken.LeftCurly != this.currentToken.token){ ReportError(JSError.NoLeftCurly); } GetNextToken(); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1 && IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exc) == -1 ){ // give up exc._partiallyComputedNode = null; throw exc; }else{ if (exc._partiallyComputedNode == null) expr = new ConstantWrapper(true, CurrentPositionContext()); else expr = exc._partiallyComputedNode; if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) != -1){ if (exc._token == JSToken.RightParen) GetNextToken(); if (JSToken.LeftCurly != this.currentToken.token){ ReportError(JSError.NoLeftCurly); } GetNextToken(); } } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet); } // parse the switch body cases = new ASTList(this.currentToken.Clone()); bool defaultStatement = false; this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); try{ while (JSToken.RightCurly != this.currentToken.token){ SwitchCase caseClause = null; AST caseValue = null; Context caseCtx = this.currentToken.Clone(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_CaseNoSkipTokenSet); try{ if (JSToken.Case == this.currentToken.token){ // get the case GetNextToken(); caseValue = ParseExpression(); }else if (JSToken.Default == this.currentToken.token){ // get the default if (defaultStatement) // we report an error but we still accept the default ReportError(JSError.DupDefault, true); else defaultStatement = true; GetNextToken(); }else{ // This is an error, there is no case or default. Assume a default was missing and keep going defaultStatement = true; ReportError(JSError.BadSwitch); } if (JSToken.Colon != this.currentToken.token) ReportError(JSError.NoColon); // read the statements inside the case or default GetNextToken(); }catch(RecoveryTokenException exc){ // right now we can only get here for the 'case' statement if (IndexOfToken(NoSkipTokenSet.s_CaseNoSkipTokenSet, exc) == -1){ // ignore the current case or default exc._partiallyComputedNode = null; throw exc; }else{ caseValue = exc._partiallyComputedNode; if (exc._token == JSToken.Colon) GetNextToken(); } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_CaseNoSkipTokenSet); } this.blockType.Add(BlockType.Block); try{ Block statements = new Block(this.currentToken.Clone()); this.noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); try{ while (JSToken.RightCurly != this.currentToken.token && JSToken.Case != this.currentToken.token && JSToken.Default != this.currentToken.token){ try{ statements.Append(ParseStatement()); }catch(RecoveryTokenException exc){ if (exc._partiallyComputedNode != null){ statements.Append(exc._partiallyComputedNode); exc._partiallyComputedNode = null; } if (IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exc) == -1) throw exc; } } }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exc) == -1){ if (null == caseValue) caseClause = new SwitchCase(caseCtx, statements); else caseClause = new SwitchCase(caseCtx, caseValue, statements); cases.Append(caseClause); throw exc; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet); } if (JSToken.RightCurly == this.currentToken.token) statements.context.UpdateWith(this.currentToken); if (null == caseValue){ caseCtx.UpdateWith(statements.context); caseClause = new SwitchCase(caseCtx, statements); }else{ caseCtx.UpdateWith(statements.context); caseClause = new SwitchCase(caseCtx, caseValue, statements); } cases.Append(caseClause); }finally{ this.blockType.RemoveAt(this.blockType.Count - 1); } } }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1){ //save what you can a rethrow switchCtx.UpdateWith(CurrentPositionContext()); exc._partiallyComputedNode = new Switch(switchCtx, expr, cases); throw exc; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } switchCtx.UpdateWith(this.currentToken); GetNextToken(); }finally{ this.blockType.RemoveAt(this.blockType.Count - 1); } return new Switch(switchCtx, expr, cases); }
private Block ParseBlock(out Context closingBraceContext) { closingBraceContext = null; this.blockType.Add(BlockType.Block); Block block = new Block(this.currentToken.Clone()); this.GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); try { while (JSToken.RightCurly != this.currentToken.token) { try { block.Append(this.ParseStatement()); continue; } catch (RecoveryTokenException exception) { if (exception._partiallyComputedNode != null) { block.Append(exception._partiallyComputedNode); } if (this.IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exception) == -1) { throw exception; } continue; } } } catch (RecoveryTokenException exception2) { if (this.IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exception2) == -1) { exception2._partiallyComputedNode = block; throw exception2; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.blockType.RemoveAt(this.blockType.Count - 1); } closingBraceContext = this.currentToken.Clone(); block.context.UpdateWith(this.currentToken); this.GetNextToken(); return block; }
internal ScriptBlock ParseExpressionItem() { int i = this.Globals.ScopeStack.Size(); try { Block block = new Block(this.sourceContext.Clone()); this.GetNextToken(); block.Append(new Expression(this.sourceContext.Clone(), this.ParseExpression())); return new ScriptBlock(this.sourceContext.Clone(), block); } catch (EndOfFile) { } catch (ScannerException exception) { this.EOFError(exception.m_errorId); } catch (StackOverflowException) { this.Globals.ScopeStack.TrimToSize(i); this.ReportError(JSError.OutOfStack, true); } return null; }
private AST ParseSwitchStatement() { Context context = this.currentToken.Clone(); AST expression = null; ASTList cases = null; this.blockType.Add(BlockType.Switch); try { this.GetNextToken(); if (JSToken.LeftParen != this.currentToken.token) { this.ReportError(JSError.NoLeftParen); } this.GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet); try { expression = this.ParseExpression(); if (JSToken.RightParen != this.currentToken.token) { this.ReportError(JSError.NoRightParen); } this.GetNextToken(); if (JSToken.LeftCurly != this.currentToken.token) { this.ReportError(JSError.NoLeftCurly); } this.GetNextToken(); } catch (RecoveryTokenException exception) { if ((this.IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exception) == -1) && (this.IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exception) == -1)) { exception._partiallyComputedNode = null; throw exception; } if (exception._partiallyComputedNode == null) { expression = new ConstantWrapper(true, this.CurrentPositionContext()); } else { expression = exception._partiallyComputedNode; } if (this.IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exception) != -1) { if (exception._token == JSToken.RightParen) { this.GetNextToken(); } if (JSToken.LeftCurly != this.currentToken.token) { this.ReportError(JSError.NoLeftCurly); } this.GetNextToken(); } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet); } cases = new ASTList(this.currentToken.Clone()); bool flag = false; this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); try { while (JSToken.RightCurly != this.currentToken.token) { SwitchCase elem = null; AST ast2 = null; Context context2 = this.currentToken.Clone(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_CaseNoSkipTokenSet); try { if (JSToken.Case == this.currentToken.token) { this.GetNextToken(); ast2 = this.ParseExpression(); } else if (JSToken.Default == this.currentToken.token) { if (flag) { this.ReportError(JSError.DupDefault, true); } else { flag = true; } this.GetNextToken(); } else { flag = true; this.ReportError(JSError.BadSwitch); } if (JSToken.Colon != this.currentToken.token) { this.ReportError(JSError.NoColon); } this.GetNextToken(); } catch (RecoveryTokenException exception2) { if (this.IndexOfToken(NoSkipTokenSet.s_CaseNoSkipTokenSet, exception2) == -1) { exception2._partiallyComputedNode = null; throw exception2; } ast2 = exception2._partiallyComputedNode; if (exception2._token == JSToken.Colon) { this.GetNextToken(); } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_CaseNoSkipTokenSet); } this.blockType.Add(BlockType.Block); try { Block statements = new Block(this.currentToken.Clone()); this.noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); try { while (((JSToken.RightCurly != this.currentToken.token) && (JSToken.Case != this.currentToken.token)) && (JSToken.Default != this.currentToken.token)) { try { statements.Append(this.ParseStatement()); continue; } catch (RecoveryTokenException exception3) { if (exception3._partiallyComputedNode != null) { statements.Append(exception3._partiallyComputedNode); exception3._partiallyComputedNode = null; } if (this.IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exception3) == -1) { throw exception3; } continue; } } } catch (RecoveryTokenException exception4) { if (this.IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exception4) == -1) { if (ast2 == null) { elem = new SwitchCase(context2, statements); } else { elem = new SwitchCase(context2, ast2, statements); } cases.Append(elem); throw exception4; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet); } if (JSToken.RightCurly == this.currentToken.token) { statements.context.UpdateWith(this.currentToken); } if (ast2 == null) { context2.UpdateWith(statements.context); elem = new SwitchCase(context2, statements); } else { context2.UpdateWith(statements.context); elem = new SwitchCase(context2, ast2, statements); } cases.Append(elem); continue; } finally { this.blockType.RemoveAt(this.blockType.Count - 1); } } } catch (RecoveryTokenException exception5) { if (this.IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exception5) == -1) { context.UpdateWith(this.CurrentPositionContext()); exception5._partiallyComputedNode = new Switch(context, expression, cases); throw exception5; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } context.UpdateWith(this.currentToken); this.GetNextToken(); } finally { this.blockType.RemoveAt(this.blockType.Count - 1); } return new Switch(context, expression, cases); }
private AST ParseVariableStatement(FieldAttributes visibility, CustomAttributeList customAttributes, JSToken kind) { Block block = new Block(this.currentToken.Clone()); bool flag = true; AST elem = null; Label_0015: this.noSkipTokenSet.Add(NoSkipTokenSet.s_EndOfLineToken); try { elem = this.ParseIdentifierInitializer(JSToken.None, visibility, customAttributes, kind); } catch (RecoveryTokenException exception) { if ((exception._partiallyComputedNode != null) && !flag) { block.Append(exception._partiallyComputedNode); block.context.UpdateWith(exception._partiallyComputedNode.context); exception._partiallyComputedNode = block; } if (this.IndexOfToken(NoSkipTokenSet.s_EndOfLineToken, exception) == -1) { throw exception; } if (flag) { elem = exception._partiallyComputedNode; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_EndOfLineToken); } if ((JSToken.Semicolon == this.currentToken.token) || (JSToken.RightCurly == this.currentToken.token)) { if (JSToken.Semicolon == this.currentToken.token) { elem.context.UpdateWith(this.currentToken); this.GetNextToken(); } } else { if (JSToken.Comma == this.currentToken.token) { flag = false; block.Append(elem); goto Label_0015; } if (!this.scanner.GotEndOfLine()) { this.ReportError(JSError.NoSemicolon, true); } } if (flag) { return elem; } block.Append(elem); block.context.UpdateWith(elem.context); return block; }
private AST ParseStaticInitializer(Context initContext) { if (this.demandFullTrustOnFunctionCreation) { new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); } Block body = null; FunctionScope item = new FunctionScope(this.Globals.ScopeStack.Peek()) { isStatic = true }; ArrayList blockType = this.blockType; this.blockType = new ArrayList(0x10); SimpleHashtable labelTable = this.labelTable; this.labelTable = new SimpleHashtable(0x10); this.blockType.Add(BlockType.Block); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); try { this.Globals.ScopeStack.Push(item); body = new Block(this.currentToken.Clone()); this.GetNextToken(); while (JSToken.RightCurly != this.currentToken.token) { try { body.Append(this.ParseStatement()); continue; } catch (RecoveryTokenException exception) { if (exception._partiallyComputedNode != null) { body.Append(exception._partiallyComputedNode); } if (this.IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exception) == -1) { throw exception; } continue; } } } catch (RecoveryTokenException exception2) { if (this.IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exception2) == -1) { exception2._partiallyComputedNode = new StaticInitializer(initContext, body, item); throw exception2; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.blockType = blockType; this.labelTable = labelTable; this.Globals.ScopeStack.Pop(); } body.context.UpdateWith(this.currentToken); initContext.UpdateWith(this.currentToken); this.GetNextToken(); return new StaticInitializer(initContext, body, item); }
private AST ParsePackage(Context packageContext) { AST ast4; this.GetNextToken(); AST expression = null; bool flag = this.scanner.GotEndOfLine(); if (JSToken.Identifier != this.currentToken.token) { if (JSScanner.CanParseAsExpression(this.currentToken.token)) { bool flag2; this.ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); expression = new Lookup("package", packageContext); expression = this.MemberExpression(expression, null); expression = this.ParsePostfixExpression(expression, out flag2); expression = this.ParseExpression(expression, false, flag2, JSToken.None); return new Expression(expression.context.Clone(), expression); } if (flag) { this.ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); return new Lookup("package", packageContext); } if ((JSToken.Increment == this.currentToken.token) || (JSToken.Decrement == this.currentToken.token)) { bool flag3; this.ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); expression = new Lookup("package", packageContext); expression = this.ParsePostfixExpression(expression, out flag3); expression = this.ParseExpression(expression, false, false, JSToken.None); return new Expression(expression.context.Clone(), expression); } } else { this.errorToken = this.currentToken; expression = this.ParseQualifiedIdentifier(JSError.NoIdentifier); } Context context = null; if ((JSToken.LeftCurly != this.currentToken.token) && (expression == null)) { context = this.currentToken.Clone(); this.GetNextToken(); } if (JSToken.LeftCurly == this.currentToken.token) { if (expression == null) { if (context == null) { context = this.currentToken.Clone(); } this.ReportError(JSError.NoIdentifier, context, true); } } else if (expression == null) { this.ReportError(JSError.SyntaxError, packageContext); if (JSScanner.CanStartStatement(context.token)) { this.currentToken = context; return this.ParseStatement(); } if (JSScanner.CanStartStatement(this.currentToken.token)) { this.errorToken = null; return this.ParseStatement(); } this.ReportError(JSError.SyntaxError); this.SkipTokensAndThrow(); } else { if (flag) { bool flag4; this.ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); Block block = new Block(packageContext.Clone()); block.Append(new Lookup("package", packageContext)); expression = this.MemberExpression(expression, null); expression = this.ParsePostfixExpression(expression, out flag4); expression = this.ParseExpression(expression, false, true, JSToken.None); block.Append(new Expression(expression.context.Clone(), expression)); block.context.UpdateWith(expression.context); return block; } this.ReportError(JSError.NoLeftCurly); } PackageScope item = new PackageScope(this.Globals.ScopeStack.Peek()); this.Globals.ScopeStack.Push(item); try { string name = (expression != null) ? expression.ToString() : "anonymous package"; item.name = name; packageContext.UpdateWith(this.currentToken); ASTList classList = new ASTList(packageContext); this.GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_PackageBodyNoSkipTokenSet); try { while (this.currentToken.token != JSToken.RightCurly) { AST statement = null; try { switch (this.currentToken.token) { case JSToken.Identifier: { bool flag6; bool canBeAttribute = true; statement = this.ParseUnaryExpression(out flag6, ref canBeAttribute, false); if (canBeAttribute) { bool flag8; statement = this.ParseAttributes(statement, true, false, out flag8); if (flag8 && (statement is Class)) { classList.Append(statement); continue; } } this.ReportError(JSError.OnlyClassesAllowed, statement.context.Clone(), true); this.SkipTokensAndThrow(); continue; } case JSToken.Interface: case JSToken.Class: { classList.Append(this.ParseClass(FieldAttributes.PrivateScope, false, this.currentToken.Clone(), false, false, null)); continue; } case JSToken.Enum: { classList.Append(this.ParseEnum(FieldAttributes.PrivateScope, this.currentToken.Clone(), null)); continue; } case JSToken.Import: { this.ReportError(JSError.InvalidImport, true); try { this.ParseImportStatement(); } catch (RecoveryTokenException) { } continue; } case JSToken.Package: { Context context2 = this.currentToken.Clone(); if (this.ParsePackage(context2) is Package) { this.ReportError(JSError.PackageInWrongContext, context2, true); } continue; } case JSToken.Internal: case JSToken.Abstract: case JSToken.Public: case JSToken.Static: case JSToken.Private: case JSToken.Protected: case JSToken.Final: { bool flag5; statement = this.ParseAttributes(null, true, false, out flag5); if (!flag5 || !(statement is Class)) { break; } classList.Append(statement); continue; } case JSToken.Semicolon: { this.GetNextToken(); continue; } case JSToken.EndOfFile: this.EOFError(JSError.ErrEOF); throw new EndOfFile(); default: goto Label_04D9; } this.ReportError(JSError.OnlyClassesAllowed, statement.context.Clone(), true); this.SkipTokensAndThrow(); continue; Label_04D9: this.ReportError(JSError.OnlyClassesAllowed, (statement != null) ? statement.context.Clone() : this.CurrentPositionContext(), true); this.SkipTokensAndThrow(); continue; } catch (RecoveryTokenException exception) { if ((exception._partiallyComputedNode != null) && (exception._partiallyComputedNode is Class)) { classList.Append((Class) exception._partiallyComputedNode); exception._partiallyComputedNode = null; } if (this.IndexOfToken(NoSkipTokenSet.s_PackageBodyNoSkipTokenSet, exception) == -1) { throw exception; } continue; } } } catch (RecoveryTokenException exception2) { if (this.IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exception2) == -1) { this.ReportError(JSError.NoRightCurly, this.CurrentPositionContext()); exception2._partiallyComputedNode = new Package(name, expression, classList, packageContext); throw exception2; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_PackageBodyNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } this.GetNextToken(); ast4 = new Package(name, expression, classList, packageContext); } finally { this.Globals.ScopeStack.Pop(); } return ast4; }
private AST ParseFunction(FieldAttributes visibilitySpec, bool inExpression, Context fncCtx, bool isMethod, bool isAbstract, bool isFinal, bool isInterface, CustomAttributeList customAttributes, Call function) { AST ast2; if (this.demandFullTrustOnFunctionCreation) { new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); } IdentifierLiteral id = null; AST rootObject = null; ArrayList parameters = null; TypeExpression expression = null; Block body = null; bool isGetter = false; bool isSetter = false; if (function == null) { this.GetNextToken(); if (isMethod) { if (JSToken.Get == this.currentToken.token) { isGetter = true; this.GetNextToken(); } else if (JSToken.Set == this.currentToken.token) { isSetter = true; this.GetNextToken(); } } if (JSToken.Identifier == this.currentToken.token) { id = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); this.GetNextToken(); if (JSToken.AccessField == this.currentToken.token) { if (isInterface) { this.ReportError(JSError.SyntaxError, true); } this.GetNextToken(); if (JSToken.Identifier == this.currentToken.token) { rootObject = new Lookup(id.context); id = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); this.GetNextToken(); while (JSToken.AccessField == this.currentToken.token) { this.GetNextToken(); if (JSToken.Identifier == this.currentToken.token) { rootObject = new Member(rootObject.context.CombineWith(this.currentToken), rootObject, new ConstantWrapper(id.ToString(), id.context)); id = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); this.GetNextToken(); } else { this.ReportError(JSError.NoIdentifier, true); } } } else { this.ReportError(JSError.NoIdentifier, true); } } } else { string identifier = JSKeyword.CanBeIdentifier(this.currentToken.token); if (identifier != null) { this.ForceReportInfo(JSError.KeywordUsedAsIdentifier, isMethod); id = new IdentifierLiteral(identifier, this.currentToken.Clone()); this.GetNextToken(); } else { if (!inExpression) { identifier = this.currentToken.GetCode(); this.ReportError(JSError.NoIdentifier, true); this.GetNextToken(); } else { identifier = ""; } id = new IdentifierLiteral(identifier, this.CurrentPositionContext()); } } } else { id = function.GetName(); } ArrayList blockType = this.blockType; this.blockType = new ArrayList(0x10); SimpleHashtable labelTable = this.labelTable; this.labelTable = new SimpleHashtable(0x10); FunctionScope item = new FunctionScope(this.Globals.ScopeStack.Peek(), isMethod); this.Globals.ScopeStack.Push(item); try { parameters = new ArrayList(); Context context = null; if (function == null) { if (JSToken.LeftParen != this.currentToken.token) { this.ReportError(JSError.NoLeftParen); } this.GetNextToken(); while (JSToken.RightParen != this.currentToken.token) { if (context != null) { this.ReportError(JSError.ParamListNotLast, context, true); context = null; } string str2 = null; TypeExpression type = null; this.noSkipTokenSet.Add(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet); try { try { if (JSToken.ParamArray == this.currentToken.token) { context = this.currentToken.Clone(); this.GetNextToken(); } if ((JSToken.Identifier != this.currentToken.token) && ((str2 = JSKeyword.CanBeIdentifier(this.currentToken.token)) == null)) { if (JSToken.LeftCurly == this.currentToken.token) { this.ReportError(JSError.NoRightParen); break; } if (JSToken.Comma == this.currentToken.token) { this.ReportError(JSError.SyntaxError, true); } else { this.ReportError(JSError.SyntaxError, true); this.SkipTokensAndThrow(); } } else { if (str2 == null) { str2 = this.scanner.GetIdentifier(); } else { this.ForceReportInfo(JSError.KeywordUsedAsIdentifier); } Context context2 = this.currentToken.Clone(); this.GetNextToken(); if (JSToken.Colon == this.currentToken.token) { type = this.ParseTypeExpression(); if (type != null) { context2.UpdateWith(type.context); } } CustomAttributeList list3 = null; if (context != null) { list3 = new CustomAttributeList(context); list3.Append(new Microsoft.JScript.CustomAttribute(context, new Lookup("...", context), new ASTList(null))); } parameters.Add(new ParameterDeclaration(context2, str2, type, list3)); } if (JSToken.RightParen == this.currentToken.token) { break; } if (JSToken.Comma != this.currentToken.token) { if (JSToken.LeftCurly == this.currentToken.token) { this.ReportError(JSError.NoRightParen); break; } if ((JSToken.Identifier == this.currentToken.token) && (type == null)) { this.ReportError(JSError.NoCommaOrTypeDefinitionError); } else { this.ReportError(JSError.NoComma); } } this.GetNextToken(); } catch (RecoveryTokenException exception) { if (this.IndexOfToken(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet, exception) == -1) { throw exception; } } continue; } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet); } } fncCtx.UpdateWith(this.currentToken); if (isGetter && (parameters.Count != 0)) { this.ReportError(JSError.BadPropertyDeclaration, true); isGetter = false; } else if (isSetter && (parameters.Count != 1)) { this.ReportError(JSError.BadPropertyDeclaration, true); isSetter = false; } this.GetNextToken(); if (JSToken.Colon == this.currentToken.token) { if (isSetter) { this.ReportError(JSError.SyntaxError); } this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); try { expression = this.ParseTypeExpression(); } catch (RecoveryTokenException exception2) { if (this.IndexOfToken(NoSkipTokenSet.s_StartBlockNoSkipTokenSet, exception2) == -1) { exception2._partiallyComputedNode = null; throw exception2; } if (exception2._partiallyComputedNode != null) { expression = (TypeExpression) exception2._partiallyComputedNode; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); } if (isSetter) { expression = null; } } } else { function.GetParameters(parameters); } if ((JSToken.LeftCurly != this.currentToken.token) && (isAbstract || (isMethod && this.GuessIfAbstract()))) { if (!isAbstract) { isAbstract = true; this.ReportError(JSError.ShouldBeAbstract, fncCtx, true); } body = new Block(this.currentToken.Clone()); } else { if (JSToken.LeftCurly != this.currentToken.token) { this.ReportError(JSError.NoLeftCurly, true); } else if (isAbstract) { this.ReportError(JSError.AbstractWithBody, fncCtx, true); } this.blockType.Add(BlockType.Block); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); try { body = new Block(this.currentToken.Clone()); this.GetNextToken(); while (JSToken.RightCurly != this.currentToken.token) { try { body.Append(this.ParseStatement()); continue; } catch (RecoveryTokenException exception3) { if (exception3._partiallyComputedNode != null) { body.Append(exception3._partiallyComputedNode); } if (this.IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exception3) == -1) { throw exception3; } continue; } } body.context.UpdateWith(this.currentToken); fncCtx.UpdateWith(this.currentToken); } catch (RecoveryTokenException exception4) { if (this.IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exception4) == -1) { this.Globals.ScopeStack.Pop(); try { ParameterDeclaration[] declarationArray = new ParameterDeclaration[parameters.Count]; parameters.CopyTo(declarationArray); if (inExpression) { exception4._partiallyComputedNode = new FunctionExpression(fncCtx, id, declarationArray, expression, body, item, visibilitySpec); } else { exception4._partiallyComputedNode = new FunctionDeclaration(fncCtx, rootObject, id, declarationArray, expression, body, item, visibilitySpec, isMethod, isGetter, isSetter, isAbstract, isFinal, customAttributes); } if (customAttributes != null) { customAttributes.SetTarget(exception4._partiallyComputedNode); } } finally { this.Globals.ScopeStack.Push(item); } throw exception4; } } finally { this.blockType.RemoveAt(this.blockType.Count - 1); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } this.GetNextToken(); } } finally { this.blockType = blockType; this.labelTable = labelTable; this.Globals.ScopeStack.Pop(); } ParameterDeclaration[] array = new ParameterDeclaration[parameters.Count]; parameters.CopyTo(array); if (inExpression) { ast2 = new FunctionExpression(fncCtx, id, array, expression, body, item, visibilitySpec); } else { ast2 = new FunctionDeclaration(fncCtx, rootObject, id, array, expression, body, item, visibilitySpec, isMethod, isGetter, isSetter, isAbstract, isFinal, customAttributes); } if (customAttributes != null) { customAttributes.SetTarget(ast2); } return ast2; }
Block ParseBlock(out Context closingBraceContext){ closingBraceContext = null; this.blockType.Add(BlockType.Block); Block codeBlock = new Block(this.currentToken.Clone()); GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); try{ try{ while (JSToken.RightCurly != this.currentToken.token){ try{ codeBlock.Append(ParseStatement()); }catch(RecoveryTokenException exc){ if (exc._partiallyComputedNode != null) codeBlock.Append(exc._partiallyComputedNode); if (IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exc) == -1) throw exc; } } }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1){ exc._partiallyComputedNode = codeBlock; throw exc; } } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.blockType.RemoveAt(this.blockType.Count - 1); } closingBraceContext = this.currentToken.Clone(); // update the block context codeBlock.context.UpdateWith(this.currentToken); GetNextToken(); return codeBlock; }
//--------------------------------------------------------------------------------------- // ParseExpressionItem // // A VSAITEMTYPE2.EXPRESSION call into here to parse an expression //--------------------------------------------------------------------------------------- internal ScriptBlock ParseExpressionItem(){ int scopeStackSize = Globals.ScopeStack.Size(); try{ Block block = new Block(this.sourceContext.Clone()); GetNextToken(); block.Append(new Expression(this.sourceContext.Clone(), ParseExpression())); return new ScriptBlock(this.sourceContext.Clone(), block); }catch (EndOfFile){ }catch (ScannerException se){ // a scanner exception implies that the end of file has been reached with an error. // Mark the end of file as the error location EOFError(se.m_errorId); } catch (StackOverflowException) { // On stack overflow, finally clauses are not executed so we explicitly // restore the global stack here. Globals.ScopeStack.TrimToSize(scopeStackSize); ReportError(JSError.OutOfStack, true); } return null; }
//--------------------------------------------------------------------------------------- // ParseVariableStatement // // VariableStatement : // ('var' | 'const') VariableDeclarationList // // VariableDeclarationList : // VariableDeclaration | // VariableDeclaration ',' VariableDeclarationList // // VariableDeclaration : // Identifier Type Initializer // // Type : // <empty> | // ':' TypeExpression // // Initializer : // <empty> | // '=' AssignmentExpression //--------------------------------------------------------------------------------------- private AST ParseVariableStatement(FieldAttributes visibility, CustomAttributeList customAttributes, JSToken kind){ Block varList = new Block(this.currentToken.Clone()); bool single = true; AST vdecl = null; for (;;){ this.noSkipTokenSet.Add(NoSkipTokenSet.s_EndOfLineToken); try{ vdecl = ParseIdentifierInitializer(JSToken.None, visibility, customAttributes, kind); }catch(RecoveryTokenException exc){ // an exception is passing by, possibly bringing some info, save the info if any if (exc._partiallyComputedNode != null){ if (!single){ varList.Append(exc._partiallyComputedNode); varList.context.UpdateWith(exc._partiallyComputedNode.context); exc._partiallyComputedNode = varList; } } if (IndexOfToken(NoSkipTokenSet.s_EndOfLineToken, exc) == -1) throw exc; else{ if (single) vdecl = exc._partiallyComputedNode; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_EndOfLineToken); } if (JSToken.Semicolon == this.currentToken.token || JSToken.RightCurly == this.currentToken.token){ if (JSToken.Semicolon == this.currentToken.token){ vdecl.context.UpdateWith(this.currentToken); GetNextToken(); } break; }else if (JSToken.Comma == this.currentToken.token){ single = false; varList.Append(vdecl); continue; }else if (this.scanner.GotEndOfLine()){ break; }else{ // assume the variable statement was terminated and move on ReportError(JSError.NoSemicolon, true); break; } } if (single) return vdecl; else{ varList.Append(vdecl); varList.context.UpdateWith(vdecl.context); return varList; } }
private Block ParseClassBody(bool isEnum, bool isInterface) { this.blockType.Add(BlockType.Block); Block block = new Block(this.currentToken.Clone()); try { this.GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); JSToken[] tokens = null; if (isEnum) { tokens = NoSkipTokenSet.s_EnumBodyNoSkipTokenSet; } else if (isInterface) { tokens = NoSkipTokenSet.s_InterfaceBodyNoSkipTokenSet; } else { tokens = NoSkipTokenSet.s_ClassBodyNoSkipTokenSet; } try { while (JSToken.RightCurly != this.currentToken.token) { if (this.currentToken.token == JSToken.EndOfFile) { this.ReportError(JSError.NoRightCurly, true); this.SkipTokensAndThrow(); } this.noSkipTokenSet.Add(tokens); try { try { AST elem = isEnum ? this.ParseEnumMember() : this.ParseClassMember(isInterface); if (elem != null) { block.Append(elem); } } catch (RecoveryTokenException exception) { if (exception._partiallyComputedNode != null) { block.Append(exception._partiallyComputedNode); } if (this.IndexOfToken(tokens, exception) == -1) { exception._partiallyComputedNode = null; throw exception; } } continue; } finally { this.noSkipTokenSet.Remove(tokens); } } } catch (RecoveryTokenException exception2) { exception2._partiallyComputedNode = block; throw exception2; } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } block.context.UpdateWith(this.currentToken); this.GetNextToken(); } finally { this.blockType.RemoveAt(this.blockType.Count - 1); } return block; }