class Parser implements IParser { private var scanner:IScanner; private var generator:CodeGenerator; private var token:Token; public function Parser (scanner:IScanner) { this.scanner = scanner; } private function getToken () : Token { return token; } private function nextToken () : Token { return (token = scanner.getToken()); } private function isToken (type:String) : Boolean { return (token.type == type); } private function isNextToken (type:String) : Boolean { return (nextToken().type == type); } private function initialize () : Void { scanner.rewind(); generator = new CodeGenerator(); breakLabelList = new Array(); continueLabelList = new Array(); functionStack = new Array(); nextToken(); } public function parse () : Array { initialize(); parse_program(); return generator.getCode(); } private function syntaxError (message:String) : Void { throw new SyntaxError('Parser [SyntaxError] on line'+scanner.getLineNumber()+' '+message+' ('+getToken().type+')'+newline+scanner.getLine()); } private var breakLabelList:Array; private function pushBreakLabel (label:Label) : Void { breakLabelList.unshift(label); } private function popBreakLabel () : Label { return Label(breakLabelList.shift()); } private function getBreakLabel () : Label { if (breakLabelList.length < 1) { syntaxError('その位置でbreakは使用できません'); } return breakLabelList[0]; } private var continueLabelList:Array; private function pushContinueLabel (label:Label) : Void { continueLabelList.unshift(label); } private function popContinueLabel () : Label { return Label(continueLabelList.shift()); } private function getContinueLabel () : Label { if (continueLabelList.length < 1) { syntaxError('その位置でcontinueは使用できません'); } return continueLabelList[0]; } private var functionStack:Array; private function beginFunction () : Void { functionStack.unshift(true); } private function endFunction () : Void { functionStack.shift(); } private function beginCoroutine () : Void { functionStack.unshift(false); } private function endCoroutine () : Void { functionStack.shift(); } private function isAllowReturn () : Boolean { return functionStack.length > 0; } private function isInFunction () : Boolean { return (functionStack.length > 0 && functionStack[0]); } // ContinueStatementから // Program ::= SourceElements // // First(Program) ::= First(SourceElements) // Follow(Program) ::= EOF private function parse_program () : Void { parse_sourceElements(); } // SourceElements ::= SourceElement // ::= SourceElements SourceElement // // First(SourceElements) ::= First(SourceElement) private function parse_sourceElements () : Void { parse_sourceElement(); // ここを常に回すようにしておかないと、コード中に予期しないトークンが // 出現したときにエラーを出せない // while (isStatementFirst(getToken().type) || isToken('function')) { while (getToken() != null) { // Follow from FunctionBody if (isToken('}')) { return; } parse_sourceElement(); } } // SourceElement ::= Statement // ::= FunctionDeclaration // ::= CorutineDeclaration (original) // // First(SourceElement) ::= First(Statement) First(FunctionDeclaration) First(CorutineDeclaration) private function parse_sourceElement () : Void { if (isToken('function')) { parse_functionDeclaration(); } else if (isToken('coroutine')) { parse_coroutineDeclaration(); } else if (isStatementFirst(getToken().type)) { parse_statement(); } else { syntaxError('SourceElementに謎のトークン'); } } // FunctionDeclaration ::= 'function' Identifier '(' FormalParameterList? ')' '{' FunctionBody '}' // // First(FunctionDeclaration) ::= 'function' private function parse_functionDeclaration () : Void { if (!isToken('function')) { syntaxError('関数宣言なのに"function"が無い??'); } if (!isNextToken('identifier')) { syntaxError('関数宣言に関数名が無い'); } var funcName:String = String(getToken().value); var label:Label = generator.putFunction(); beginFunction(); generator.beginNewScope(); if (!isNextToken('(')) { syntaxError('関数宣言で"("を忘れている'); } if (isNextToken('identifier')) { parse_formalParameterList(); } if (!isToken(')')) { syntaxError('関数宣言で")"を忘れている'); } if (!isNextToken('{')) { syntaxError('関数宣言で"{"を忘れている'); } if (!isNextToken('}')) { parse_functionBody(); } if (!hasLastReturn) { generator.putReturnFunction(ExpressionResult.createLiteral(undefined)); } if (!isToken('}')) { syntaxError('関数宣言で"}"を忘れている'); } endFunction(); generator.closeScope(); generator.setLabel(label); generator.putSetLocalVariable(funcName, ExpressionResult.createStack()); generator.popAndDestroyStack(); nextToken(); } // FunctionExpression ::= 'function' Identifier? '(' FormalParamaterList? ')' '{' FunctionBody '}' // // First(FunctionExpression) ::= 'function' private function parse_functionExpression (expressionResult:ExpressionResult) : Void { if (!isToken('function')) { syntaxError('関数宣言なのに"function"が無い??'); } var funcName:String = null; if (isNextToken('identifier')) { funcName = String(getToken().value); nextToken(); } var label:Label = generator.putFunction(); beginFunction(); generator.beginNewScope(); if (!isToken('(')) { syntaxError('関数宣言で"("を忘れている'); } if (isNextToken('identifier')) { parse_formalParameterList(); } if (!isToken(')')) { syntaxError('関数宣言で")"を忘れている'); } if (!isNextToken('{')) { syntaxError('関数宣言で"{"を忘れている'); } if (!isNextToken('}')) { parse_functionBody(); } if (!hasLastReturn) { generator.putReturnFunction(ExpressionResult.createLiteral(undefined)); } if (!isToken('}')) { syntaxError('関数宣言で"}"を忘れている'); } generator.closeScope(); endFunction(); generator.setLabel(label); if (funcName != null) { generator.putSetLocalVariable(funcName, ExpressionResult.createStack()); } expressionResult.setTypeStack(); nextToken(); } // CoroutineDeclaration ::= 'coroutine' Identifier? '(' FormalParamaterList? ')' '{' FunctionBody '}' // // First(CoroutineDeclaration) ::= 'coroutine' private function parse_coroutineDeclaration (expressionResult:ExpressionResult) : Void { if (!isToken('coroutine')) { syntaxError('コルーチン宣言なのに"coroutine"が無い??'); } if (!isNextToken('identifier')) { syntaxError('コルーチン宣言に関数名が無い'); } var funcName:String = String(getToken().value); var label:Label = generator.putCoroutine(); beginCoroutine(); generator.beginNewScope(); if (!isNextToken('(')) { syntaxError('コルーチン宣言で"("を忘れている'); } if (isNextToken('identifier')) { parse_formalParameterList(); } if (!isToken(')')) { syntaxError('コルーチン宣言で")"を忘れている'); } if (!isNextToken('{')) { syntaxError('コルーチン宣言で"{"を忘れている'); } if (!isNextToken('}')) { parse_functionBody(); } if (!hasLastReturn) { generator.putReturnCoroutine(ExpressionResult.createLiteral(undefined)); } if (!isToken('}')) { syntaxError('コルーチン宣言で"}"を忘れている'); } generator.closeScope(); endCoroutine(); generator.setLabel(label); generator.putSetLocalVariable(funcName, ExpressionResult.createStack()); generator.popAndDestroyStack(); expressionResult.setTypeStack(); nextToken(); } // CoroutineExpression ::= 'coroutine' Identifier? '(' FormalParamaterList? ')' '{' FunctionBody '}' // // First(CoroutineExpression) ::= 'coroutine' private function parse_coroutineExpression (expressionResult:ExpressionResult) : Void { if (!isToken('coroutine')) { syntaxError('コルーチン宣言なのに"coroutine"が無い??'); } var funcName:String = null; if (isNextToken('identifier')) { funcName = String(getToken().value); nextToken(); } var label:Label = generator.putCoroutine(); beginCoroutine(); generator.beginNewScope(); if (!isToken('(')) { syntaxError('コルーチン宣言で"("を忘れている'); } if (isNextToken('identifier')) { parse_formalParameterList(); } if (!isToken(')')) { syntaxError('コルーチン宣言で")"を忘れている'); } if (!isNextToken('{')) { syntaxError('コルーチン宣言で"{"を忘れている'); } if (!isNextToken('}')) { parse_functionBody(); } if (!hasLastReturn) { generator.putReturnCoroutine(ExpressionResult.createLiteral(undefined)); } if (!isToken('}')) { syntaxError('コルーチン宣言で"}"を忘れている'); } generator.closeScope(); endCoroutine(); generator.setLabel(label); if (funcName != null) { generator.putSetLocalVariable(funcName, ExpressionResult.createStack()); } expressionResult.setTypeStack(); nextToken(); } // FormalParameterList ::= Identifier // ::= FormalParameterList ',' Identifier // // First(FormalParameterList) ::= identifier private function parse_formalParameterList () : Void { var argumentIndex:Number = 0; for (;;) { if (!isToken('identifier')) { syntaxError('パラメータ名が必要です'); } generator.putArgument(argumentIndex, String(getToken().value)); argumentIndex++; if (isNextToken(',')) { nextToken(); continue; } break; } } // FunctionBody ::= SourceElements // // First(FunctionBody) ::= First(SourceElements) private function parse_functionBody () : Void { parse_sourceElements(); } private var hasLastReturn:Boolean; // Statement ::= Block // ::= VariableStatement // ::= EmptyStatement // ::= ExpressionStatement // ::= IfStatement // ::= IterationStatement // ::= ContinueStatement // ::= BreakStatement // ::= ReturnStatement // ::= WithStatement // ::= LabelledStatement (not support) // ::= SwitchStatement // ::= SuspendStatement (original) // ::= LoopStatement (original) // ::= ThrowStatement (not support) // ::= TryStatement (not support) // // First(Statement) ::= ... private function parse_statement () : Void { hasLastReturn = false; // for FunctionExpression, FunctionDeclaration var stackBegin:Number = generator.getStackLength(); switch (getToken().type) { case '{': parse_block(); break; case 'var': parse_variableStatement(); break; case ';': parse_emptyStatement(); break; case 'if': parse_ifStatement(); break; case 'do': case 'while': case 'for': parse_iterationStatement(); break; case 'continue': parse_continueStatement(); break; case 'break': parse_breakStatement(); break; case 'return': parse_returnStatement(); break; case 'with': parse_withStatement(); break; case 'switch': parse_switchStatement(); break; case 'yield': parse_yieldStatement(); break; case 'suspend': parse_suspendStatement(); break; case 'loop': parse_loopStatement(); break; default: { if (isExpressionFirst(getToken().type)) { parse_expressionStatement(); break; } syntaxError('ステートメントに予期しないトークンがあります'); } case 'function': { syntaxError('ステートメント内では関数を定義できません'); break; } } generator.cleanUpStack(stackBegin); } private function isStatementFirst (type:String) : Boolean { return (type == '{' || type == 'var' || type == ';' || type == 'if' || type == 'do' || type == 'while' || type == 'for' || type == 'for' || type == 'continue' || type == 'break' || type == 'return' || type == 'with' || type == 'switch' || type == 'yield' || type == 'suspend' || type == 'loop' || (type != 'function' && type != 'coroutine' && /*type != '{' &&*/ isExpressionFirst(type)) ); } // Block ::= '{' StatementList? '}' // // First(Block) ::= '{' private function parse_block () : Void { if (!isToken('{')) { syntaxError('ブロック開始で"{"が無い??'); } if (!isNextToken('}')) { parse_statementList(); } if (!isToken('}')) { syntaxError('ブロック終了の"}"を忘れている'); } nextToken(); } // StatementList ::= Statement // ::= StatementList Statement // // First(StatementList) ::= First(Statement) private function parse_statementList () : Void { parse_statement(); for (;;) { // Follow from Block, CaseClause, DefaultClause if (isToken('}')) { return; } if (isStatementFirst(getToken().type)) { parse_statement(); continue; } break; } } // VariableStatement ::= 'var' VariableDeclarationList ';' // // First(VariableStatement) ::= 'var' private function parse_variableStatement () : Void { if (!isToken('var')) { syntaxError('変数宣言で"var"が無い??'); } nextToken(); parse_variableDeclarationList(); if (!isToken(';')) { syntaxError('変数宣言で";"を忘れている'); } nextToken(); } // VariableDeclarationList ::= VariableDeclaration // ::= VariableDeclarationList ',' VariableDeclaration // // First(VariableDeclarationList) ::= First(VariableDeclaration) private function parse_variableDeclarationList () : Void { parse_variableDeclaration(); for (;;) { if (isToken(',')) { nextToken(); parse_variableDeclaration(); continue; } break; } } // VariableDeclaration ::= Identifier Initialiser? // // First(VariableDeclaration) ::= identifier private function parse_variableDeclaration () : Void { if (!isToken('identifier')) { syntaxError('変数宣言で変数名が無い'); } var identifier:String = String(getToken().value); if (isNextToken('=')) { var rightExpression:ExpressionResult = new ExpressionResult(); parse_initialiser(rightExpression); generator.putExpressionResult(rightExpression); generator.putSetLocalVariable(identifier, rightExpression); generator.popAndDestroyStack(); } else { generator.putSetLocalVariable(identifier, ExpressionResult.createLiteral(undefined)); generator.popAndDestroyStack(); } } // initialiser ::= '=' AssignmentExpression // // First(Initialiser) ::= '=' private function parse_initialiser (expressionResult:ExpressionResult) : Void { if (!isToken('=')) { syntaxError('イニシャライザで"="が無い??'); } nextToken(); parse_assignmentExpression(expressionResult); } // EmptyStatement ::= ';' // // First(EmptyStatement) ::= ';' private function parse_emptyStatement () : Void { if (!isToken(';')) { syntaxError('空ステートメントで";"が無い??'); } nextToken(); } // ExpressionStatement ::= [lookahead { '{' , 'function' } ] Expression ';' // // First(ExpressionStatement) ::= First(Expression) private function parse_expressionStatement () : Void { if (isToken('{') || isToken('function')) { syntaxError('ExpressionStatementで曖昧トークン'); } var expressionResult:ExpressionResult = new ExpressionResult(); parse_expression(expressionResult); generator.putExpressionResult(expressionResult); if (!isToken(';')) { syntaxError('式ステートメントで";"を忘れている'); } nextToken(); } // IfStatement ::= 'if' '(' Expression ')' Statement 'else' Statement // ::= 'if' '(' Expression ')' Statement // // First(IfStatement) ::= 'if' private function parse_ifStatement () : Void { if (!isToken('if')) { syntaxError('ifステートメントで"if"が無い??'); } if (!isNextToken('(')) { syntaxError('ifステートメントで"("が無い'); } nextToken(); var condition:ExpressionResult = new ExpressionResult(); parse_expression(condition); if (!isToken(')')) { syntaxError('ifステートメントで")"を忘れている'); } generator.putExpressionResult(condition); var endIfLabel:Label = new Label(); generator.putIf(condition, endIfLabel); nextToken(); parse_statement(); if (isToken('else')) { var endElseLabel:Label = new Label(); generator.putJump(endElseLabel); generator.setLabel(endIfLabel); nextToken(); parse_statement(); generator.setLabel(endElseLabel); } else { generator.setLabel(endIfLabel); } } // IterationiStatement ::= 'do' Statement 'while' '(' Expression ')' // ::= 'while' '(' Expression ')' Statement // ::= 'for' '(' Expression? ';' Expression? ':' Expression? ')' Statement // ::= 'for' '(' 'var' VariableDeclaration ';' Expression? ';' Expression? ')' Statement // // First(IterationStatement) ::= 'do' 'while' 'for' private function parse_iterationStatement () : Void { if (isToken('for')) { parse_forStatement(); } else if (isToken('while')) { parse_whileStatement(); } else if (isToken('do')) { parse_doStatement(); } else { syntaxError('ループステートメントで謎のトークン'); } } private function parse_forStatement () : Void { if (!isNextToken('(')) { syntaxError('for文の"("が無い'); } var conditionLabel:Label = new Label(); var continueLabel:Label = new Label(); var startLabel:Label = new Label(); var endLabel:Label = new Label(); pushBreakLabel(endLabel); pushContinueLabel(continueLabel); // initialize expression, or variable declaration if (isNextToken('var')) { nextToken(); parse_variableDeclaration(); } else { if (!isToken(';')) { var stackBegin:Number = generator.getStackLength(); var initializeExpression:ExpressionResult = new ExpressionResult(); parse_expression(initializeExpression); generator.putExpressionResult(initializeExpression); generator.cleanUpStack(stackBegin); } } if (!isToken(';')) { syntaxError('for文の最初の";"が無い'); } generator.setLabel(conditionLabel); // condition expression if (!isNextToken(';')) { var stackBegin:Number = generator.getStackLength(); var conditionExpression:ExpressionResult = new ExpressionResult(); parse_expression(conditionExpression); generator.putExpressionResult(conditionExpression); generator.putIf(conditionExpression, endLabel); generator.cleanUpStack(stackBegin); } if (!isToken(';')) { syntaxError('for文のふたつめの";"が無い'); } generator.putJump(startLabel); generator.setLabel(continueLabel); // continue expression if (!isNextToken(')')) { var stackBegin:Number = generator.getStackLength(); var continueExpression:ExpressionResult = new ExpressionResult(); parse_expression(continueExpression); generator.putExpressionResult(continueExpression); generator.cleanUpStack(stackBegin); } generator.putJump(conditionLabel); if (!isToken(')')) { syntaxError('for文の")"を忘れている'); } nextToken(); generator.setLabel(startLabel); parse_statement(); generator.putJump(continueLabel); generator.setLabel(endLabel); popContinueLabel(); popBreakLabel(); } private function parse_whileStatement () : Void { if (!isNextToken('(')) { syntaxError('while文の"("が無い'); } nextToken(); var startLabel:Label = new Label(); var endLabel:Label = new Label(); pushBreakLabel(endLabel); pushContinueLabel(startLabel); generator.setLabel(startLabel); var condition:ExpressionResult = new ExpressionResult(); parse_expression(condition); generator.putExpressionResult(condition); generator.putIf(condition, endLabel); if (!isToken(')')) { syntaxError('while文の")"を忘れている'); } nextToken(); parse_statement(); generator.putJump(startLabel); generator.setLabel(endLabel); popContinueLabel(); popBreakLabel(); } private function parse_doStatement () : Void { nextToken(); var startLabel:Label = new Label(); var continueLabel:Label = new Label(); var endLabel:Label = new Label(); pushBreakLabel(endLabel); pushContinueLabel(continueLabel); generator.setLabel(startLabel); parse_statement(); if (!isToken('while')) { syntaxError('doに対応するwhileが無い'); } if (!isNextToken('(')) { syntaxError('do-whileの"("が無い'); } nextToken(); generator.setLabel(continueLabel); var condition:ExpressionResult = new ExpressionResult(); parse_expression(condition); generator.putExpressionResult(condition); generator.putIf(condition, endLabel); generator.putJump(startLabel); if (!isToken(')')) { syntaxError('do-whileの")"を忘れている'); } generator.setLabel(endLabel); popContinueLabel(); popBreakLabel(); nextToken(); } // ContinueStatement ::= 'continue' Identifier? ';' // *not support Identifier // // First(ContinueStatement) ::= 'continue' private function parse_continueStatement () : Void { if (!isToken('continue')) { syntaxError('continueで"continue"が無い??'); } if (!isNextToken(';')) { syntaxError('continueで";"を忘れている'); } generator.putJump(getContinueLabel()); nextToken(); } // BreakStatement ::= 'break' Identifier? ';' // *not support Identifier // // First(BreakStatement) ::= 'break' private function parse_breakStatement () : Void { if (!isToken('break')) { syntaxError('breakで"break"が無い??'); } if (!isNextToken(';')) { syntaxError('breakで";"を忘れている'); } generator.putJump(getBreakLabel()); nextToken(); } // ReturnStatement ::= 'return' Expression? ';' // // FIrst(ReturnStatement) ::= 'return' private function parse_returnStatement () : Void { if (!isToken('return')) { syntaxError('returnで"return"が無い??'); } if (!isAllowReturn()) { syntaxError('returnは関数又はコルーチン内でのみ使えます'); } hasLastReturn = true; // for FunctionExpression, FunctionDeclaration var returnValue:ExpressionResult; if (isExpressionFirst(nextToken().type)) { returnValue = new ExpressionResult(); parse_expression(returnValue); generator.putExpressionResult(returnValue); } else { returnValue = ExpressionResult.createLiteral(undefined); } if (isInFunction()) { generator.putReturnFunction(returnValue); } else { generator.putReturnCoroutine(returnValue); } if (!isToken(';')) { syntaxError('returnで";"を忘れている'); } nextToken(); } // WithStatement ::= 'with' '(' Expression ')' Statement // // First(WithStatement) ::= 'with' private function parse_withStatement () : Void { if (!isToken('with')) { syntaxError('withで"with"が無い??'); } if (!isNextToken('(')) { syntaxError('withで"("が無い'); } nextToken(); var objectExpression:ExpressionResult = new ExpressionResult(); parse_expression(objectExpression); generator.putExpressionResult(objectExpression); generator.putWith(objectExpression); generator.beginNewScope(); if (!isToken(')')) { syntaxError('withで")"を忘れている'); } nextToken(); parse_statement(); generator.closeScope(); generator.putEndWith(); } // SwitchStatement ::= 'switch' '(' Expression ')' CaseBlock // // First(SwitchStatement) ::= 'switch' private function parse_switchStatement () : Void { if (!isToken('switch')) { syntaxError('switchで"switch"が無い??'); } if (!isNextToken('(')) { syntaxError('switchで"("を忘れている'); } nextToken(); var condition:ExpressionResult = new ExpressionResult(); parse_expression(condition); generator.putExpressionResult(condition); if (!isToken(')')) { syntaxError('switchで")"を忘れている'); } var endLabel:Label = new Label(); pushBreakLabel(endLabel); nextToken(); parse_caseBlock(condition); generator.setLabel(endLabel); popBreakLabel(); } // CaseBlcok ::= '{' CaseClauses? '}' // ::= '{' CaseClauses? DefaultClause CaseClauses? '}' // // First(CaseBlock) ::= '{' private function parse_caseBlock (condition:ExpressionResult) : Void { if (!isToken('{')) { syntaxError('switch-caseの"{"が無い'); } var caseLabel:Label = new Label(); var bodyLabel:Label = new Label(); if (isNextToken('case')) { parse_caseClauses(condition, caseLabel, bodyLabel); } if (isToken('default')) { var defaultLabel:Label = new Label(); generator.setLabel(defaultLabel); parse_defaultClause(bodyLabel); if (isToken('case')) { parse_caseClauses(condition, caseLabel, bodyLabel); } generator.setLabelAddress(caseLabel, defaultLabel.address); generator.setLabel(bodyLabel); } else { generator.setLabel(caseLabel); generator.setLabel(bodyLabel); } if (!isToken('}')) { syntaxError('switch-caseで"}"を忘れている'); } nextToken(); } // CaseClauses ::= CaseClause // ::= CaseClauses CaseClause // // First(CaseClauses) ::= First(CaseClause) private function parse_caseClauses (condition:ExpressionResult, caseLabel:Label, bodyLabel:Label) : Void { while (isToken('case')) { parse_caseClause(condition, caseLabel, bodyLabel); } } // CaseClause ::= 'case' Expression ':' StatementList? // // First(CaseClause) ::= 'case' private function parse_caseClause (condition:ExpressionResult, caseLabel:Label, bodyLabel:Label) : Void { if (!isToken('case')) { syntaxError('caseで"case"が無い??'); } generator.setLabel(caseLabel); caseLabel.initialize(); if (!condition.isLiteral()) { generator.putDuplicate(condition); } nextToken(); var caseCondition:ExpressionResult = new ExpressionResult(); parse_expression(caseCondition); generator.putExpressionResult(caseCondition); generator.putBinaryOperation('CSEQ', condition, caseCondition); generator.putIf(ExpressionResult.createStack(), caseLabel); if (!isToken(':')) { syntaxError('caseで":"が無い'); } generator.setLabel(bodyLabel); bodyLabel.initialize(); if (isStatementFirst(nextToken().type)) { parse_statementList(); } generator.putJump(bodyLabel); } // DefaultClause ::= 'default' ':' StatementList? // // First(DefaultClause) ::= 'default' private function parse_defaultClause (bodyLabel:Label) : Void { if (!isToken('default')) { syntaxError('defaultで"default"が無い??'); } if (!isNextToken(':')) { syntaxError('defaultで":"を忘れている'); } generator.setLabel(bodyLabel); bodyLabel.initialize(); if (isStatementFirst(nextToken().type)) { parse_statementList(); } generator.putJump(bodyLabel); } // YieldStatement ::= 'yield' ';' // *original // // First(YieldStatement) ::= 'yield' private function parse_yieldStatement () : Void { if (!isToken('yield')) { syntaxError('yieldで"yield"が無い??'); } if (!isNextToken(';')) { syntaxError('yieldで";"を忘れている'); } if (isInFunction()) { syntaxError('関数内でyieldする事は出来ません。coroutineを使う必要があります。'); } generator.putSuspend(); nextToken(); } // SuspendStatement ::= 'suspend' ';' // *original // // First(SuspendStatement) ::= 'suspend' private function parse_suspendStatement () : Void { if (!isToken('suspend')) { syntaxError('suspendで"suspend"が無い??'); } if (!isNextToken(';')) { syntaxError('suspendで";"を忘れている'); } if (isInFunction()) { syntaxError('関数内でsuspendする事は出来ません。coroutineを使う必要があります。'); } generator.putSuspend(); nextToken(); } // LoopStatement ::= 'loop' 'Statement // *original // // First(LoopStatement) ::= 'loop' private function parse_loopStatement () : Void { if (!isToken('loop')) { syntaxError('loopで"loop"が無い??'); } nextToken(); var startLabel:Label = new Label(); var endLabel:Label = new Label(); pushBreakLabel(endLabel); pushContinueLabel(startLabel); generator.setLabel(startLabel); parse_statement(); generator.putJump(startLabel); generator.setLabel(endLabel); popContinueLabel(); popBreakLabel(); } // Expression ::= AssignmentExpression // ::= Expression ',' AssignmentExpression // // First(Expression) ::= First(AssignmentExpression) private function parse_expression (expressionResult:ExpressionResult) : Void { parse_assignmentExpression(expressionResult); while (isToken(',')) { nextToken(); generator.putExpressionResult(expressionResult); generator.popAndDestroyStack(); expressionResult.initialize(); parse_assignmentExpression(expressionResult); } } private function isExpressionFirst (type:String) : Boolean { return isUnaryExpressionFirst(type); } private function areBothLiteral (a:ExpressionResult, b:ExpressionResult) : Boolean { return (a.isType('literal') && b.isType('literal')); } // AssignmentExpression ::= ConditionalExpression // ::= LeftHandSideExpression AssignmentOperator AssignmentExpression // AssignmentOperator ::= '=' '*=' '/=' '%=' '+=' '-=' '<<=' '>>=' '>>>=' '&=' '^=' '|=' // // First(AssignmentExpression) ::= First(ConditionalExpression) First(LeftHandSideExpression) private function parse_assignmentExpression (expressionResult:ExpressionResult) : Void { parse_conditionalExpression(expressionResult); switch (getToken().type) { case '=': { nextToken(); switch (expressionResult.type) { case 'member': { var objectExpression:ExpressionResult = expressionResult.getObjectExpression(); var memberExpression:ExpressionResult = expressionResult.getMemberExpression(); generator.putExpressionResult(memberExpression); var rightExpression:ExpressionResult = new ExpressionResult(); parse_assignmentExpression(rightExpression); generator.putExpressionResult(rightExpression); generator.putSetMember(objectExpression, memberExpression, rightExpression); } break; case 'variable': { var rightExpression:ExpressionResult = new ExpressionResult(); parse_assignmentExpression(rightExpression); generator.putExpressionResult(rightExpression); generator.putSetVariable(String(expressionResult.value), rightExpression); } break; default: { syntaxError('左辺値は変数又はプロパティでなければなりません'); } } expressionResult.setTypeStack(); } break; case '*=': case '/=': case '%=': case '+=': case '-=': case '<<=': case '>>=': case '>>>=': case '&=': case '^=': case '|=': { var operation:String; switch (getToken().type) { case '*=': operation = 'MUL'; break; case '/=': operation = 'DIV'; break; case '%=': operation = 'MOD'; break; case '+=': operation = 'ADD'; break; case '-=': operation = 'SUB'; break; case '<<=': operation = 'LSH'; break; case '>>=': operation = 'RSH'; break; case '>>>=': operation = 'URSH'; break; case '&=': operation = 'AND'; break; case '^=': operation = 'XOR'; break; case '|=': operation = 'OR'; break; } nextToken(); switch (expressionResult.type) { case 'member': { var objectExpression:ExpressionResult = expressionResult.getObjectExpression(); var memberExpression:ExpressionResult = expressionResult.getMemberExpression(); if (!memberExpression.isLiteral()) { generator.putExpressionResult(memberExpression); var s:Number = generator.popStack(); generator.putDuplicate(memberExpression); generator.pushStack(s); generator.putDuplicate(objectExpression); generator.swapStack(1, 2); } else { generator.putDuplicate(objectExpression); } generator.putGetMember(objectExpression, memberExpression); expressionResult.setTypeStack(); var rightExpression:ExpressionResult = new ExpressionResult(); parse_assignmentExpression(rightExpression); generator.putExpressionResult(rightExpression); generator.putBinaryOperation(operation, expressionResult, rightExpression); generator.putSetMember(objectExpression, memberExpression, expressionResult); } break; case 'variable': { var identifier:String = String(expressionResult.value); generator.putGetVariable(identifier); expressionResult.setTypeStack(); var rightExpression:ExpressionResult = new ExpressionResult(); parse_assignmentExpression(rightExpression); generator.putExpressionResult(rightExpression); generator.putBinaryOperation(operation, expressionResult, rightExpression); generator.putSetVariable(identifier, expressionResult); } break; default: { syntaxError('左辺値は変数又はプロパティでなければなりません'); } } expressionResult.setTypeStack(); } break; default: break; } } // ConditionalExpression ::= LogicalORExpression // ::= LogicalORExpression '?' AssignmentExpression ':' AssignmentExpression // // First(ConditionalExpression) ::= First(LogicalORExpression) private function parse_conditionalExpression (expressionResult:ExpressionResult) : Void { parse_logicalORExpression(expressionResult); if (isToken('?')) { generator.putExpressionResult(expressionResult); var label:Label = new Label(); generator.putIf(expressionResult, label); nextToken(); expressionResult.initialize(); parse_assignmentExpression(expressionResult); if (expressionResult.isType('literal')) { generator.putLiteral(expressionResult); } else { generator.putExpressionResult(expressionResult); } var patch:Number = generator.popStack(); var label2:Label = new Label(); generator.putJump(label2); generator.setLabel(label); if (!isToken(':')) { syntaxError('3項演算式で":"が無い'); } nextToken(); expressionResult.initialize(); parse_assignmentExpression(expressionResult); if (expressionResult.isType('literal')) { generator.putLiteral(expressionResult); } else { generator.putExpressionResult(expressionResult); } expressionResult.setType('stack'); generator.setStackPatch(patch); generator.setLabel(label2); } } // LogicalORExpression ::= LogicalANDExpression // ::= LogicalORExpression '||' LogicalANDExpression // // First(LogicalORExpression) ::= First(LogicalANDExpression) private function parse_logicalORExpression (expressionResult:ExpressionResult) : Void { parse_logicalANDExpression(expressionResult); while (isToken('||')) { nextToken(); // ここどうにかならんかなぁ・・・ generator.putExpressionResult(expressionResult); generator.putDuplicate(expressionResult); var patch:Number = generator.popStack(); expressionResult.setType('stack'); var label:Label = new Label(); generator.putNif(expressionResult, label); expressionResult.initialize(); parse_logicalANDExpression(expressionResult); if (expressionResult.isType('literal')) { generator.putLiteral(expressionResult); } else { generator.putExpressionResult(expressionResult); } generator.setStackPatch(patch); expressionResult.setType('stack'); generator.setLabel(label); } } // LogicalANDExpression ::= BitwiseORExpression // ::= LogicalANDExpression '&&' BitwiseORExpression // // First(LogicalANDExpression) ::= First(BitwiseORExpression) private function parse_logicalANDExpression (expressionResult:ExpressionResult) : Void { parse_bitwiseORExpression(expressionResult); while (isToken('&&')) { nextToken(); // ここどうにかならんかなぁ・・・ generator.putExpressionResult(expressionResult); generator.putDuplicate(expressionResult); var patch:Number = generator.popStack(); expressionResult.setType('stack'); var label:Label = new Label(); generator.putIf(expressionResult, label); expressionResult.initialize(); parse_bitwiseORExpression(expressionResult); if (expressionResult.isType('literal')) { generator.putLiteral(expressionResult); } else { generator.putExpressionResult(expressionResult); } generator.setStackPatch(patch); expressionResult.setType('stack'); generator.setLabel(label); } } // BitwiseORExpression ::= BitwiseXORExpression // ::= BitwiseORExpression '|' BitwiseXORExpression // // First(BitwiseORExpression) ::= First(BitwiseXORExpression) private function parse_bitwiseORExpression (expressionResult:ExpressionResult) : Void { parse_bitwiseXORExpression(expressionResult); while (isToken('|')) { var operation:String = getToken().type; nextToken(); generator.putExpressionResult(expressionResult); var rightExpressionResult:ExpressionResult = new ExpressionResult(); parse_bitwiseXORExpression(rightExpressionResult); generator.putExpressionResult(rightExpressionResult); // 定数畳み込み if (areBothLiteral(expressionResult, rightExpressionResult)) { expressionResult.setValue(expressionResult.value | rightExpressionResult.value); } // 通常コード else { generator.putBinaryOperation('OR', expressionResult, rightExpressionResult); expressionResult.setType('stack'); } } } // BitwiseXORExpression ::= BitwiseANDExpression // ::= BitiwseXORExpression '^' BitwiseANDExpression // // First(BitwiseXORExpression) ::= First(BitwiseANDExpression) private function parse_bitwiseXORExpression (expressionResult:ExpressionResult) : Void { parse_bitwiseANDExpression(expressionResult); while (isToken('^')) { var operation:String = getToken().type; nextToken(); generator.putExpressionResult(expressionResult); var rightExpressionResult:ExpressionResult = new ExpressionResult(); parse_bitwiseANDExpression(rightExpressionResult); generator.putExpressionResult(rightExpressionResult); // 定数畳み込み if (areBothLiteral(expressionResult, rightExpressionResult)) { expressionResult.setValue(expressionResult.value ^ rightExpressionResult.value); } else { generator.putBinaryOperation('XOR', expressionResult, rightExpressionResult); expressionResult.setType('stack'); } } } // BitwiseANDExpression ::= EqualityExpression // ::= BitwiseANDExpression '&' EqualityExpression // // First(BitwiseANDExpression) ::= First(EqualityEpxression) private function parse_bitwiseANDExpression (expressionResult:ExpressionResult) : Void { parse_equalityExpression(expressionResult); while (isToken('&')) { var operation:String = getToken().type; nextToken(); generator.putExpressionResult(expressionResult); var rightExpressionResult:ExpressionResult = new ExpressionResult(); parse_equalityExpression(rightExpressionResult); generator.putExpressionResult(rightExpressionResult); // 定数畳み込み if (areBothLiteral(expressionResult, rightExpressionResult)) { expressionResult.setValue(expressionResult.value & rightExpressionResult.value); } else { generator.putBinaryOperation('AND', expressionResult, rightExpressionResult); expressionResult.setType('stack'); } } } // EqualityExpression ::= RelationalExpression // ::= EqualityExpression '==' RelationalExpression // ::= EqualityExpression '!=' RelationalExpression // ::= EqualityExpression '===' RelationalExpression // ::= EqualityExpression '!==' RelationalExpression // // FIrst(EqualityEpxression) ::= First(RelationalExpression) private function parse_equalityExpression (expressionResult:ExpressionResult) : Void { parse_relationalExpression(expressionResult); while (isToken('==') || isToken('!=') || isToken('===') || isToken('!==')) { var operation:String = getToken().type; nextToken(); generator.putExpressionResult(expressionResult); var rightExpressionResult:ExpressionResult = new ExpressionResult(); parse_relationalExpression(rightExpressionResult); generator.putExpressionResult(rightExpressionResult); if (areBothLiteral(expressionResult, rightExpressionResult)) { switch (operation) { case '==': expressionResult.setValue(expressionResult.value == rightExpressionResult.value); break; case '!=': expressionResult.setValue(expressionResult.value != rightExpressionResult.value); break; case '===': expressionResult.setValue(expressionResult.value === rightExpressionResult.value); break; case '!==': expressionResult.setValue(expressionResult.value !== rightExpressionResult.value); break; } } else { switch (operation) { case '==': generator.putBinaryOperation('CEQ', expressionResult, rightExpressionResult); break; case '!=': generator.putBinaryOperation('CNE', expressionResult, rightExpressionResult); break; case '===': generator.putBinaryOperation('CSEQ', expressionResult, rightExpressionResult); break; case '!==': generator.putBinaryOperation('CSNE', expressionResult, rightExpressionResult); break; } expressionResult.setType('stack'); } } } // RelationalExpression ::= ShiftExpression // ::= RelationalExpression '<' ShiftExpression // ::= RelationalExpressioin '>' ShiftExpression // ::= RelationalExpression '<=' ShiftExpression // ::= RelationalExpression '>=' ShiftExpression // ::= RelationalExpression 'instanceof' ShiftExpression // ::= RelationalExpression 'in' ShiftExpression (not support) // // First(RelationalExpression) ::= First(ShiftExpression) private function parse_relationalExpression (expressionResult:ExpressionResult) : Void { parse_shiftExpression(expressionResult); while (isToken('<') || isToken('>') || isToken('<=') || isToken('>=') || isToken('instanceof')) { var operation:String = getToken().type; nextToken(); generator.putExpressionResult(expressionResult); var rightExpressionResult:ExpressionResult = new ExpressionResult(); parse_shiftExpression(rightExpressionResult); generator.putExpressionResult(rightExpressionResult); if (areBothLiteral(expressionResult, rightExpressionResult)) { switch (operation) { case '<': expressionResult.setValue(expressionResult.value < rightExpressionResult.value); break; case '>': expressionResult.setValue(expressionResult.value > rightExpressionResult.value); break; case '<=': expressionResult.setValue(expressionResult.value <= rightExpressionResult.value); break; case '>=': expressionResult.setValue(expressionResult.value >= rightExpressionResult.value); break; case 'instanceof': expressionResult.setValue(expressionResult.value instanceof rightExpressionResult.value); break; } } else { switch (operation) { case '<': generator.putBinaryOperation('CLT', expressionResult, rightExpressionResult); break; case '>': generator.putBinaryOperation('CGT', expressionResult, rightExpressionResult); break; case '<=': generator.putBinaryOperation('CLE', expressionResult, rightExpressionResult); break; case '>=': generator.putBinaryOperation('CGE', expressionResult, rightExpressionResult); break; case 'instanceof': generator.putBinaryOperation('INSOF', expressionResult, rightExpressionResult); break; } expressionResult.setType('stack'); } } } // ShiftExpression ::= AdditiveExpression // ::= ShiftExpression '<<' AdditiveExpression // ::= ShiftExpression '>>' AdditiveExpression // ::= ShiftExpression '>>>' AdditiveExpression // // First(ShiftExpression) ::= First(AdditiveExpression) private function parse_shiftExpression (expressionResult:ExpressionResult) : Void { parse_additiveExpression(expressionResult); while (isToken('<<') || isToken('>>') || isToken('>>>')) { var operation:String = getToken().type; nextToken(); generator.putExpressionResult(expressionResult); var rightExpressionResult:ExpressionResult = new ExpressionResult(); parse_additiveExpression(rightExpressionResult); generator.putExpressionResult(rightExpressionResult); if (areBothLiteral(expressionResult, rightExpressionResult)) { switch (operation) { case '<<': expressionResult.setValue(expressionResult.value << rightExpressionResult.value); break; case '>>': expressionResult.setValue(expressionResult.value >> rightExpressionResult.value); break; case '>>>': expressionResult.setValue(expressionResult.value >>> rightExpressionResult.value); break; } } else { switch (operation) { case '<<': generator.putBinaryOperation('LSH', expressionResult, rightExpressionResult); break; case '>>': generator.putBinaryOperation('RSH', expressionResult, rightExpressionResult); break; case '>>>': generator.putBinaryOperation('URSH', expressionResult, rightExpressionResult); break; } expressionResult.setType('stack'); } } } // AdditiveExpression ::= MultiplicativeExpression // ::= AdditiveExpression '+' MultiplicativeExpression // ::= AddtivieExpression '-' MultiplicativeExpression // // First(AdditiveExpression) ::= First(MultiplicativeExpression) private function parse_additiveExpression (expressionResult:ExpressionResult) : Void { parse_multiplicativeExpression(expressionResult); while (isToken('+') || isToken('-')) { var operation:String = getToken().type; nextToken(); generator.putExpressionResult(expressionResult); var rightExpressionResult:ExpressionResult = new ExpressionResult(); parse_multiplicativeExpression(rightExpressionResult); generator.putExpressionResult(rightExpressionResult); if (areBothLiteral(expressionResult, rightExpressionResult)) { switch (operation) { case '+': expressionResult.setValue(expressionResult.value + rightExpressionResult.value); break; case '-': expressionResult.setValue(expressionResult.value - rightExpressionResult.value); break; } } else { switch (operation) { case '+': generator.putBinaryOperation('ADD', expressionResult, rightExpressionResult); break; case '-': generator.putBinaryOperation('SUB', expressionResult, rightExpressionResult); break; } expressionResult.setType('stack'); } } } // MultiplicativeExpression ::= UnaryExpression // ::= MultiplicativeExpression '*' UnaryExpression // ::= MultiplicativeExpression '/' UnaryExpression // ::= MultiplicativeExpression '%' UnaryExpression // // First(MultiplicativeExpression) ::= First(UnaryEpxression) private function parse_multiplicativeExpression (expressionResult:ExpressionResult) : Void { parse_unaryExpression(expressionResult); while (isToken('*') || isToken('/') || isToken('%')) { var operation:String = getToken().type; nextToken(); generator.putExpressionResult(expressionResult); var rightExpressionResult:ExpressionResult = new ExpressionResult(); parse_unaryExpression(rightExpressionResult); generator.putExpressionResult(rightExpressionResult); if (areBothLiteral(expressionResult, rightExpressionResult)) { switch (operation) { case '*': expressionResult.setValue(expressionResult.value * rightExpressionResult.value); break; case '/': expressionResult.setValue(expressionResult.value / rightExpressionResult.value); break; case '%': expressionResult.setValue(expressionResult.value % rightExpressionResult.value); break; } } else { switch (operation) { case '*': generator.putBinaryOperation('MUL', expressionResult, rightExpressionResult); break; case '/': generator.putBinaryOperation('DIV', expressionResult, rightExpressionResult); break; case '%': generator.putBinaryOperation('MOD', expressionResult, rightExpressionResult); break; } expressionResult.setType('stack'); } } } // UnaryExpression ::= PostfixExpression // ::= 'delete' UnaryExpression // ::= 'void' UnaryExpression // ::= 'typeof' UnaryExpression // ::= '++' UnaryExpression // ::= '--' UnaryExpression // ::= '+' UnaryExpression // ::= '-' UnaryExpression // ::= '~' UnaryExpression // ::= '!' UnaryExpression // // First(UnaryExpression) ::= First(PostfixExpression) 'delete' 'void' 'typeof' '++' '--' '-+' '-' '~' '!' private function parse_unaryExpression (expressionResult:ExpressionResult) : Void { switch (getToken().type) { case 'delete': { nextToken(); parse_unaryExpression(expressionResult); switch (expressionResult.type) { case 'member': { var objectExpression:ExpressionResult = expressionResult.getObjectExpression(); var memberExpression:ExpressionResult = expressionResult.getMemberExpression(); generator.putExpressionResult(memberExpression); generator.putDeleteMember(objectExpression, memberExpression); } break; case 'variable': { generator.putDelete(expressionResult); } break; default: { generator.putExpressionResult(expressionResult); generator.putDelete(expressionResult); } break; } expressionResult.setTypeStack(); } break; case 'void': { // 今の所無視 nextToken(); parse_unaryExpression(expressionResult); } break; case 'typeof': { nextToken(); parse_unaryExpression(expressionResult); generator.putExpressionResult(expressionResult); if (expressionResult.isType('literal')) { expressionResult.setValue(typeof expressionResult.value); } else { generator.putUnaryOperation('TYPEOF', expressionResult); expressionResult.setTypeStack(); } } break; case '++': { nextToken(); parse_unaryExpression(expressionResult); generator.putIncrement(expressionResult); expressionResult.setTypeStack(); } break; case '--': { nextToken(); parse_unaryExpression(expressionResult); generator.putDecrement(expressionResult); expressionResult.setTypeStack(); } break; case '+': { nextToken(); parse_unaryExpression(expressionResult); } break; case '-': { nextToken(); parse_unaryExpression(expressionResult); generator.putExpressionResult(expressionResult); if (expressionResult.isType('literal')) { expressionResult.setValue(-expressionResult.value); } else { var zeroLiteral:ExpressionResult = new ExpressionResult(); zeroLiteral.setTypeAndValue('literal', 0); generator.putBinaryOperation('SUB', zeroLiteral, expressionResult); expressionResult.setType('stack'); } } break; case '~': { nextToken(); parse_unaryExpression(expressionResult); generator.putExpressionResult(expressionResult); if (expressionResult.isType('literal')) { expressionResult.setValue(~expressionResult.value); } else { generator.putUnaryOperation('NOT', expressionResult); expressionResult.setType('stack'); } } break; case '!': { nextToken(); parse_unaryExpression(expressionResult); generator.putExpressionResult(expressionResult); if (expressionResult.isType('literal')) { expressionResult.setValue(!expressionResult.value); } else { generator.putUnaryOperation('LNOT', expressionResult); expressionResult.setType('stack'); } } break; default: { parse_postfixExpression(expressionResult); } break; } } private function isUnaryExpressionFirst (type:String) : Boolean { return (type == 'delete' || type == 'void' || type == 'typeof' || type == '++' || type == '--' || type == '+' || type == '-' || type == '~' || type == '!' || isMemberExpressionFirst(type) ); } // PostfixExpression ::= LeftHandSideExpression // ::= LeftHandSideExpression '++' // ::= LeftHandSideExpression '--' // // First(PostfixExpression) ::= First(LeftHandSideExpression) private function parse_postfixExpression (expressionResult:ExpressionResult) : Void { parse_leftHandSideExpression(expressionResult); if (isToken('++') || isToken('--')) { switch (getToken().type) { case '++': generator.putPostfixIncrement(expressionResult); break; case '--': generator.putPostfixDecrement(expressionResult); break; } expressionResult.setTypeStack(); nextToken(); } } // LeftHandSideExpression ::= NewExpression // ::= CallExpression // NewExpression ::= MemberExpression // ::= 'new' NewExpression (not support) // CallExpression ::= MemberExpression Arguments // ::= CallExpression Arguments // ::= CallExpression '[' Expression ']' // ::= CallExpression '.' Identifier // // ↑じゃ解析できないので // // LeftHandSideExpression ::= CallExpression // CallExpression ::= MemberExpression // ::= CallExpression Arguments // ::= CallExpression '[' Expression ']' // ::= CallExpression '.' Identifier // MemberExpression ::= PrimaryExpression // ::= FunctionExpression // ::= CoroutineExpression // ::= 'new' MemberExpression Arguments? // // First(LeftHandSideExpression) ::= First(CallExpression) // First(CallExpression) ::= First(MemberExpression) // First(MemberExpression) ::= First(PrimaryExpression) First(FunctionExpression) First(CoroutineExpression) 'new' private function parse_leftHandSideExpression (expressionResult:ExpressionResult) : Void { parse_callExpression(expressionResult); } private function parse_callExpression (expressionResult:ExpressionResult) : Void { parse_memberExpression(expressionResult); for (;;) { if (isToken('(')) { var numOfArguments:Number = parse_arguments(); switch (expressionResult.type) { case 'member': { var objectExpression:ExpressionResult = expressionResult.getObjectExpression(); var memberExpression:ExpressionResult = expressionResult.getMemberExpression(); generator.putExpressionResult(memberExpression); generator.putCallMember(objectExpression, memberExpression, numOfArguments); } break; case 'stack': { generator.putCallFunctor(numOfArguments); } break; default: { generator.putCall(expressionResult, numOfArguments); } } expressionResult.setType('stack'); continue; } if (isToken('[')) { nextToken(); generator.putExpressionResult(expressionResult); var memberExpression:ExpressionResult = new ExpressionResult(); parse_expression(memberExpression); expressionResult.setTypeMember(expressionResult.clone(), memberExpression); // expressionResult.setTypeAndValue('member', memberExpression); if (!isToken(']')) { syntaxError('配列アクセス演算子の"]"を忘れている'); } nextToken(); continue; } if (isToken('.')) { generator.putExpressionResult(expressionResult); if (!isNextToken('identifier')) { syntaxError('プロパティアクセスで"."の後の識別子が無い'); } expressionResult.setTypeMember(expressionResult.clone(), ExpressionResult.createLiteral(getToken().value)); // expressionResult.setTypeAndValue('member', ExpressionResult.createLiteral(getToken().value)); nextToken(); continue; } break; } } private function parse_memberExpression (expressionResult:ExpressionResult) : Void { switch (getToken().type) { case 'function': { parse_functionExpression(expressionResult); } break; case 'coroutine': { parse_coroutineExpression(expressionResult); } break; case 'new': { nextToken(); parse_memberExpression(expressionResult); generator.putExpressionResult(expressionResult); var numOfArguments:Number = 0; if (isToken('(')) { numOfArguments += parse_arguments(); } generator.putNew(numOfArguments); expressionResult.setType('stack'); } break; default: { parse_primaryExpression(expressionResult); } } } private function isMemberExpressionFirst (type:String) : Boolean { return (type == 'new' || type == 'function' || isPrimaryExpressionFirst(type)); } // Arguments ::= '(' ')' // ::= '(' ArgumentList ')' // // First(Arguments) ::= '(' private function parse_arguments () : Number { if (!isToken('(')) { syntaxError('呼び出し引数で"("が無い'); } var numOfArguments:Number = 0; if (!isNextToken(')')) { numOfArguments += parse_argumentList(); } if (!isToken(')')) { syntaxError('呼び出し引数で")"が無い'); } nextToken(); return numOfArguments; } // ArgumentList ::= AssignmentExpression // ::= ArgumentList ',' AssignmentExpression // // First(ArgumentList) ::= First(AssignmentExpression) private function parse_argumentList () : Number { var numOfArguments:Number = 0; for (;;) { var expressionResult:ExpressionResult = new ExpressionResult(); parse_assignmentExpression(expressionResult); generator.putExpressionResult(expressionResult); generator.putPush(expressionResult); numOfArguments++; if (isToken(',')) { nextToken(); continue; } break; } return numOfArguments; } // PrimaryExpression ::= 'this' // ::= Identifier // ::= Literal // ::= ArrayLiteral // ::= ObjectLiteral // ::= '(' Expression ')' // // First(PrimaryExpression) ::= 'this' Identifier Literal First(ArrayLiteral) First(ObjectLiteral) '(' private function parse_primaryExpression (expressionResult:ExpressionResult) : Void { switch (getToken().type) { case 'this': { generator.putThis(); expressionResult.setType('stack'); nextToken(); } break; case 'identifier': { expressionResult.setTypeAndValue('variable', getToken().value); nextToken(); } break; case 'string': case 'number': case 'bool': case 'null': case 'undefined': { expressionResult.setTypeAndValue('literal', getToken().value); nextToken(); } break; case '[': { var numOfElements:Number = parse_arrayLiteral(); generator.putArrayLiteral(numOfElements); expressionResult.setType('stack'); } break; case '{': { var numOfProperties:Number = parse_objectLiteral(); generator.putObjectLiteral(numOfProperties); expressionResult.setType('stack'); } break; case '(': { nextToken(); parse_expression(expressionResult); if (!isToken(')')) { syntaxError('式で")"を忘れている'); } nextToken(); } break; default: { syntaxError('式中に謎のトークン'); } break; } } private function isPrimaryExpressionFirst (type:String) : Boolean { return (type == 'this' || type == 'identifier' || type == 'string' || type == 'number' || type == 'bool' || type == 'undefined' || type == 'null' || type == '{' || type == '[' || type == '(' ); } // ArrayLiteral ::= '[' Elision? ']' // ::= '[' ElementList ']' // ::= '[' ElementList ',' Elision? ']' // // First(ArrayLiteral) ::= '[' private function parse_arrayLiteral () : Number { if (!isToken('[')) { syntaxError('配列初期化子で"["が無い??'); } var numOfElements:Number = 0; if (!isNextToken(']')) { if (isToken(',')) { numOfElements += parse_elision(); } if (!isToken(']')) { numOfElements += parse_elementList(); } if (isToken(',')) { numOfElements += parse_elision(); } } if (!isToken(']')) { syntaxError('配列初期化子で"]"を忘れている'); } nextToken(); return numOfElements; } // Elision ::= ',' // ::= Elision ',' // // First(Elision) ::= ',' private function parse_elision () : Number { if (!isToken(',')) { syntaxError('Elisionで","が無い??'); } var numOfElements:Number = 1; var undefinedLiteral:ExpressionResult = ExpressionResult.createLiteral(undefined); for (;;) { generator.putPush(undefinedLiteral); numOfElements++; if (isNextToken(',')) { continue; } break; } if (isToken(']')) { generator.putPush(undefinedLiteral); numOfElements++; } return numOfElements; } // ElementList ::= Elision? AssignmentExpression // ::= ElementList ',' Elision? AssignmentExpression // // First(ElementList) ::= First(Elision) First(AssignmentExpression) private function parse_elementList () : Number { var numOfElements:Number = 0; for (;;) { if (isToken(',')) { numOfElements += parse_elision(); continue; } if (isToken(']')) { break; } var expressionResult:ExpressionResult = new ExpressionResult(); parse_assignmentExpression(expressionResult); generator.putExpressionResult(expressionResult); generator.putPush(expressionResult); numOfElements++; if (isToken(',')) { nextToken(); continue; } break; } return numOfElements; } // ObjectLiteral ::= '{' '}' // ::= '{' PropertyNameAndValueList '}' // // First(ObjectLiteral) ::= '{' private function parse_objectLiteral () : Number { if (!isToken('{')) { syntaxError('オブジェクト初期化子で"{"が無い??'); } var numOfProperties:Number = 0; if (!isNextToken('}')) { numOfProperties += parse_propertyNameAndValueList(); } if (!isToken('}')) { syntaxError('オブジェクト初期化子で"}"を忘れている'); } nextToken(); return numOfProperties; } // PropertyNameAndValueList ::= PropertyName ':' AssignmentExpression // ::= PropertyNameAndValueList ',' PropertyName ':' AssignmentExpression // // First(PropertyNameAndValueList) ::= First(PropertyName) private function parse_propertyNameAndValueList () : Number { var numOfProperties:Number = 0; for (;;) { parse_propertyName(); if (!isToken(':')) { syntaxError('オブジェクト初期化子で":"が無い'); } nextToken(); var expressionResult:ExpressionResult = new ExpressionResult(); parse_assignmentExpression(expressionResult); generator.putExpressionResult(expressionResult); generator.putPush(expressionResult); numOfProperties++; if (isToken(',')) { nextToken(); continue; } break; } return numOfProperties; } // PropertyName ::= Identifier // ::= StringLiteral // ::= NumericLiteral // // First(PropertyName) ::= Identifier StringLiteral NumericLiteral private function parse_propertyName () : Void { switch (getToken().type) { case 'identifier': case 'string': case 'number': { var propertyName:ExpressionResult = ExpressionResult.createLiteral(getToken().value); generator.putPush(propertyName); nextToken(); } break; default: { syntaxError('プロパティ名で謎のトークン'); } break; } } }