public static ASTNode Compile(string source) { ScriptParseContext ctx = new ScriptParseContext { lexer = new Lexer(new StringReader(source), new TokenDefinition[] { TD_SPACE, TD_COMMENT, TD_INT, TD_FLOAT, TD_BOOL, TD_STR, TD_ID, TD_LEFT_BRACE, TD_RIGHT_BRACE, TD_LEFT_PAREN, TD_RIGHT_PAREN, TD_COMMA, TD_AT, TD_QUESTION, TD_SEMI, TD_GTEQ, TD_LTEQ, TD_GT, TD_LT, TD_EQ, TD_NEQ, TD_ASSIGN, TD_COLON, TD_EXCLAIM } ), }; var t1 = DateTime.Now; var ret = ParseNode(ctx); var t2 = DateTime.Now; Debug.Log("[BTScript] Compilation took " + (t2 - t1).Milliseconds + " ms."); return(ret); }
static ASTNode ParseNode(ScriptParseContext ctx) { var lexer = ctx.lexer; string head = _Expect(lexer, TK_ID, TK_COLON, TK_AT, TK_QUESTION, TK_EXCLAIM); object headToken = lexer.Token; if (headToken == TK_ID) // Control node { var nodeName = head; var node = ASTControlNode.Create(nodeName, lexer.LineNumber); _Expect(lexer, TK_LEFT_BRACE); while (true) // parse child nodes { ASTNode n = ParseNode(ctx); node.children.Add(n); // Peek next lexeme _Expect(lexer, TK_ID, TK_COLON, TK_AT, TK_QUESTION, TK_RIGHT_BRACE, TK_EXCLAIM); if (lexer.Token == TK_RIGHT_BRACE) { break; } lexer.PushCurrent(); // Save last token for subsequent parsing } return(node); } else if (headToken == TK_COLON) // Decorator node { string nodeName = _Expect(lexer, TK_ID); var node = ASTDecoratorNode.Create(nodeName, lexer.LineNumber); _Expect(lexer, TK_LEFT_PAREN, TK_ID, TK_AT, TK_QUESTION, TK_COLON, TK_EXCLAIM); if (lexer.Token == TK_LEFT_PAREN) { while (true) { var look2 = _Expect(lexer, TK_RIGHT_PAREN, TK_INT, TK_FLOAT, TK_STR); if (lexer.Token == TK_RIGHT_PAREN) { break; } else { object arg; if (lexer.Token == TK_INT) { arg = int.Parse(look2); } else if (lexer.Token == TK_FLOAT) { arg = float.Parse(look2); } else // TK_STR { arg = look2.Substring(1, look2.Length - 2); } node.args.Add(new SerializableArg(arg)); _Expect(lexer, TK_COMMA, TK_RIGHT_PAREN); if (lexer.Token == TK_RIGHT_PAREN) { lexer.PushCurrent(); } } } } else { lexer.PushCurrent(); } node.target = ParseNode(ctx); return(node); } else if (headToken == TK_AT) // Action node { string actionName = _Expect(lexer, TK_ID); var node = ASTActionNode.Create(actionName, lexer.LineNumber); _Expect(lexer, TK_LEFT_PAREN, TK_SEMI); if (lexer.Token == TK_SEMI) { return(node); } else { while (true) { string look1 = _Expect(lexer, TK_RIGHT_PAREN, TK_ID); if (lexer.Token == TK_RIGHT_PAREN) { break; } else { string argName = look1; _Expect(lexer, TK_ASSIGN); object arg = ParseArg(lexer); var wrapped = new SerializableArgPair { name = argName, arg = new SerializableArg(arg) }; node.args.Add(wrapped); _Expect(lexer, TK_COMMA, TK_RIGHT_PAREN); if (lexer.Token == TK_RIGHT_PAREN) { lexer.PushCurrent(); } } } _Expect(lexer, TK_SEMI); return(node); } } else if (headToken == TK_EXCLAIM) { string argName = _Expect(lexer, TK_ID); _Expect(lexer, TK_ASSIGN); object arg = ParseArg(lexer); _Expect(lexer, TK_SEMI); var node = ASTSetConditionNode.Create(lexer.LineNumber); node.condName = argName; node.arg = new SerializableArg(arg); return(node); } else // TK_QUESTION, Condition node { Debug.Assert(headToken == TK_QUESTION); string tk = _Expect(lexer, TK_EXCLAIM, TK_ID); string condName; if (lexer.Token != TK_EXCLAIM) { condName = tk; _Expect(lexer, TK_SEMI, TK_LTEQ, TK_LT, TK_GTEQ, TK_GT, TK_EQ, TK_NEQ); if (lexer.Token == TK_SEMI) // boolean condition node { var node = ASTConditionNode.Create(lexer.LineNumber); node.condName = condName; node.arg.objValue = true; return(node); } else // value condition node { CompareOp op = GetCompareOp(lexer.Token as TokenType); string val = _Expect(lexer, TK_FLOAT, TK_INT); var floatVal = float.Parse(val); var node = ASTConditionNode.Create(lexer.LineNumber); node.condName = condName; node.arg.objValue = floatVal; node.op = op; _Expect(lexer, TK_SEMI); return(node); } } else { condName = _Expect(lexer, TK_ID); if (lexer.Token == TK_ID) { var conditionNode = ASTConditionNode.Create(lexer.LineNumber); conditionNode.condName = condName; conditionNode.arg.type = ConditionType.Bool; conditionNode.op = CompareOp.NotEq; _Expect(lexer, TK_SEMI); return(conditionNode); } else { throw _Error(lexer, "only bool varible can be place after '? !'"); } } } }