AST* ParseAssignment(ParserState* parser) { AST *lvalue; enum Semantic sem = SEM_ASSIGNMENT; if(parser->currentToken.type == TOKEN_LOCAL) { Match(parser, TOKEN_LOCAL); sem = SEM_LOCAL_ASSIGNMENT; } if(parser->nextToken.type == TOKEN_LEFT_SQUARE_BRACKET) { lvalue = ParseArrayIndexing(parser); } else if(parser->nextToken.type == TOKEN_DOT) { lvalue = ParseField(parser); } else { Value *id = Match(parser, TOKEN_ID); lvalue = CreateASTNode(SEM_ID, id); } Match(parser, TOKEN_ASSIGNMENT); AST *expr = ParseExpression(parser); AST *assignment = CreateASTNode(sem, VALUE_EMPTY); AddASTChild(assignment, lvalue); AddASTChild(assignment, expr); return assignment; }
AST* ParseLogicalExpression(ParserState* parser) { AST* valueNode = ParseValue(parser); AST* lexpNode = NULL; switch(parser->currentToken.type) { case TOKEN_LT: lexpNode = CreateASTNode(SEM_LT, VALUE_EMPTY); break; case TOKEN_EQ: lexpNode = CreateASTNode(SEM_EQ, VALUE_EMPTY); break; case TOKEN_GT: lexpNode = CreateASTNode(SEM_GT, VALUE_EMPTY); break; case TOKEN_LTE: lexpNode = CreateASTNode(SEM_LTE, VALUE_EMPTY); break; case TOKEN_GTE: lexpNode = CreateASTNode(SEM_GTE, VALUE_EMPTY); break; default: return valueNode; } Advance(parser); AST* rhs = ParseValue(parser); AddASTChild(lexpNode, valueNode); AddASTChild(lexpNode, rhs); return lexpNode; }
/* Without priorities yet */ AST* ParseCondition(ParserState* parser) { if(parser->currentToken.type == TOKEN_NOT) { AST* notCond = CreateASTNode(SEM_NOT, VALUE_EMPTY); Match(parser, TOKEN_NOT); AddASTChild(notCond, ParseLogicalExpression(parser)); return notCond; } else { AST* lexp = ParseLogicalExpression(parser); AST* rhs; enum TokenType type = parser->currentToken.type; if(type == TOKEN_AND || type == TOKEN_OR) { Match(parser, type); rhs = ParseCondition(parser); AST *log_node = CreateASTNode(type == TOKEN_AND ? SEM_AND : SEM_OR, VALUE_EMPTY); AddASTChild(log_node, lexp); AddASTChild(log_node, rhs); return log_node; } return lexp; } }
ASTTree ParseCommand(char **cmdTokens, int tokenCnt) { if (tokenCnt <= 0) return NULL; int i; for (i = tokenCnt-1; i >= 0; i--) { char *token = cmdTokens[i]; if (strcmp(token, "|") == 0) { // Create a pipe node cmdTokens[i] = NULL; ASTNode *pipeNode = CreateASTNode(); pipeNode->type = PipeCommand; pipeNode->u.pipe.leftCommand = ParseCommand(cmdTokens, i); pipeNode->u.pipe.rightCommand = ParseCommand(cmdTokens+i+1, tokenCnt-i-1); return pipeNode; } else if (strcmp(token, ">") == 0) { // If > appears, must be > file in the end. Nothing more. // don't support > sth < sth2 if (cmdTokens[i+1] == NULL) { perror("Wrong syntax: > should be followed by a file name."); return NULL; } cmdTokens[i] = NULL; ASTNode *outNode = CreateASTNode(); outNode->type = OutRedirCommand; outNode->u.out.command = ParseCommand(cmdTokens, tokenCnt-2); outNode->u.out.outFile = cmdTokens[i+1]; return outNode; } else if (strcmp(token, ">>") == 0) { if (cmdTokens[i+1] == NULL) { perror("Wrong syntax: >> should be followed by a file name."); return NULL; } cmdTokens[i] = NULL; ASTNode *appNode = CreateASTNode(); appNode->type = OutAppendCommand; appNode->u.app.command = ParseCommand(cmdTokens, tokenCnt-2); appNode->u.app.appendFile = cmdTokens[i+1]; return appNode; } else if (strcmp(token, "<") == 0) { if (cmdTokens[i+1] == NULL) { perror("Wrong syntax: < should be followed by a file name."); return NULL; } cmdTokens[i] = NULL; ASTNode *inpNode = CreateASTNode(); inpNode->type = InpRedirCommand; inpNode->u.inp.command = ParseCommand(cmdTokens, tokenCnt-2); inpNode->u.inp.inpFile = cmdTokens[i+1]; return inpNode; } } // Prim Command ASTNode *primNode = CreateASTNode(); primNode->type = PrimCommand; primNode->u.prim.cmdTokens = cmdTokens; return primNode; }
AST* ParseField(ParserState* parser) { Value* id = Match(parser, TOKEN_ID); Match(parser, TOKEN_DOT); Value* field_name = Match(parser, TOKEN_FIELD); AST* ast = CreateASTNode(SEM_FIELD, id); AddASTChild(ast, CreateASTNode(SEM_CONSTANT, field_name)); return ast; }
AST* ParseObject(ParserState* parser) { if(parser->currentToken.type == TOKEN_OBJECT) { Match(parser, TOKEN_OBJECT); return CreateASTNode(SEM_OBJECT, VALUE_EMPTY); } else { Match(parser, TOKEN_NEW); AST* constructor_call = ParseFunctionCall(parser); AST* ast = CreateASTNode(SEM_NEW, VALUE_EMPTY); AddASTChild(ast, constructor_call); return ast; } }
AST* ParsePrint(ParserState* parser) { Match(parser, TOKEN_PRINT); AST* printNode = CreateASTNode(SEM_PRINT, VALUE_EMPTY); AST* exprNode = ParseExpression(parser); printNode->child = exprNode; return printNode; }
AST* ParseOperatorList(ParserState* parser) { AST *operators = CreateASTNode(SEM_EMPTY, VALUE_EMPTY); while(parser->currentToken.type != TOKEN_END) { AST *op = ParseOperator(parser); AddASTChild(operators, op); } return operators; }
AST* ParseReturn(ParserState* parser) { Match(parser, TOKEN_RETURN); AST* node = CreateASTNode(SEM_RETURN, VALUE_EMPTY); AST* ret_expr = ParseExpression(parser); AddASTChild(node, ret_expr); return node; }
AST* ParseArrayIndexing(ParserState* parser) { Value* id = Match(parser, TOKEN_ID); Match(parser, TOKEN_LEFT_SQUARE_BRACKET); AST* index = ParseExpression(parser); Match(parser, TOKEN_RIGHT_SQUARE_BRACKET); AST* ast = CreateASTNode(SEM_INDEX, id); AddASTChild(ast, index); return ast; }
AST* ParseArray(ParserState* parser) { Match(parser, TOKEN_ARRAY); Match(parser, TOKEN_LEFT_SQUARE_BRACKET); AST* size_expr = ParseExpression(parser); Match(parser, TOKEN_RIGHT_SQUARE_BRACKET); AST* node = CreateASTNode(SEM_ARRAY, VALUE_EMPTY); AddASTChild(node, size_expr); return node; }
AST* ParseExpression(ParserState* parser) { switch(parser->currentToken.type) { case TOKEN_INTREAD: Match(parser, TOKEN_INTREAD); return CreateASTNode(SEM_INTREAD, VALUE_EMPTY); case TOKEN_READ: Match(parser, TOKEN_READ); return CreateASTNode(SEM_READ, VALUE_EMPTY); case TOKEN_ARRAY: return ParseArray(parser); case TOKEN_OBJECT: case TOKEN_NEW: return ParseObject(parser); case TOKEN_FUNCTION: return ParseFunctionDefinition(parser); default: return ParseArithmeticalExpression(parser); } assert(0); return NULL; }
AST* ParseFunctionCall(ParserState* parser) { Value* funcId = Match(parser, TOKEN_ID); AST* funcNode = CreateASTNode(SEM_FUNCCALL, funcId); Match(parser, TOKEN_LEFTBRACKET); AST* arglist = ParseArgumentList(parser); Match(parser, TOKEN_RIGHTBRACKET); AddASTChild(funcNode, arglist); return funcNode; }
AST* ParseTerm(ParserState* parser) { AST* valueNode = ParseValue(parser); if(parser->currentToken.type == TOKEN_STAR) { Match(parser, TOKEN_STAR); AST* exprNode = CreateASTNode(SEM_MULTIPLICATION, VALUE_EMPTY); AddASTChild(exprNode, valueNode); AddASTChild(exprNode, ParseTerm(parser)); return exprNode; } else if(parser->currentToken.type == TOKEN_SLASH) { Match(parser, TOKEN_SLASH); AST* exprNode = CreateASTNode(SEM_DIVISION, VALUE_EMPTY); AddASTChild(exprNode, valueNode); AddASTChild(exprNode, ParseTerm(parser)); return exprNode; } else { return valueNode; } }
AST* ParseArithmeticalExpression(ParserState* parser) { AST* termNode = ParseTerm(parser); if(parser->currentToken.type == TOKEN_PLUS) { Match(parser, TOKEN_PLUS); AST* exprNode = CreateASTNode(SEM_ADDITION, VALUE_EMPTY); AddASTChild(exprNode, termNode); AddASTChild(exprNode, ParseArithmeticalExpression(parser)); return exprNode; } else if(parser->currentToken.type == TOKEN_MINUS) { Match(parser, TOKEN_MINUS); AST* exprNode = CreateASTNode(SEM_SUBTRACTION, VALUE_EMPTY); AddASTChild(exprNode, termNode); AddASTChild(exprNode, ParseArithmeticalExpression(parser)); return exprNode; } else { return termNode; } }
AST* ParseArgumentList(ParserState* parser) { AST* arglist = CreateASTNode(SEM_EMPTY, VALUE_EMPTY); /* FIXME: At this time, ArgumentList is used both for calling * and defining functions, which is wrong as it allows using * constants as formal arguments of a function */ while(parser->currentToken.type != TOKEN_RIGHTBRACKET) { AST* argument = ParseValue(parser); AddASTChild(arglist, argument); if(parser->currentToken.type != TOKEN_RIGHTBRACKET) Match(parser, TOKEN_COMMA); } return arglist; }
AST* ParseWhileCycle(ParserState* parser) { Match(parser, TOKEN_WHILE); AST* whileNode = CreateASTNode(SEM_WHILE_CYCLE, VALUE_EMPTY); AST* condition = ParseCondition(parser); Match(parser, TOKEN_DO); AST* op = ParseOperator(parser); AddASTChild(whileNode, condition); AddASTChild(whileNode, op); return whileNode; }
AST* ParseValue(ParserState* parser) { AST* node; if(parser->currentToken.type == TOKEN_NUMBER || parser->currentToken.type == TOKEN_STRING) { node = CreateASTNode(SEM_CONSTANT, parser->currentToken.value); Match(parser, parser->currentToken.type); } else { if(parser->nextToken.type == TOKEN_LEFTBRACKET) return ParseFunctionCall(parser); Value *id = Match(parser, TOKEN_ID); /* XXX: Factor this out */ if(parser->currentToken.type == TOKEN_LEFT_SQUARE_BRACKET) { Match(parser, TOKEN_LEFT_SQUARE_BRACKET); AST* size = ParseExpression(parser); Match(parser, TOKEN_RIGHT_SQUARE_BRACKET); node = CreateASTNode(SEM_INDEX, id); AddASTChild(node, size); } else if(parser->currentToken.type == TOKEN_DOT) { Match(parser, TOKEN_DOT); Value* field_name = Match(parser, TOKEN_FIELD); if(parser->currentToken.type == TOKEN_LEFTBRACKET) { node = CreateASTNode(SEM_METHOD_CALL, VALUE_EMPTY); AST* field_node = CreateASTNode(SEM_FIELD, id); AddASTChild(field_node, CreateASTNode(SEM_CONSTANT, field_name)); AddASTChild(node, field_node); Match(parser, TOKEN_LEFTBRACKET); AddASTChild(node, ParseArgumentList(parser)); Match(parser, TOKEN_RIGHTBRACKET); } else { node = CreateASTNode(SEM_FIELD, id); AddASTChild(node, CreateASTNode(SEM_CONSTANT, field_name)); } } else { node = CreateASTNode(SEM_ID, id); } } return node; }
AST* ParseFunctionDefinition(ParserState* parser) { Match(parser, TOKEN_FUNCTION); Value* name = NULL; if(parser->currentToken.type == TOKEN_ID) { name = Match(parser, TOKEN_ID); } AST* function = CreateASTNode(SEM_FUNCTION, name); Match(parser, TOKEN_LEFTBRACKET); AST* arglist = ParseArgumentList(parser); Match(parser, TOKEN_RIGHTBRACKET); AST* code = ParseBlock(parser); AddASTChild(function, arglist); AddASTChild(function, code); return function; }
AST* ParseIfStatement(ParserState* parser) { Match(parser, TOKEN_IF); AST* ifNode = CreateASTNode(SEM_IF_STATEMENT, VALUE_EMPTY); AST* condition = ParseCondition(parser); Match(parser, TOKEN_THEN); AST* thenOp = ParseOperator(parser); AddASTChild(ifNode, condition); AddASTChild(ifNode, thenOp); if(parser->currentToken.type == TOKEN_ELSE) { Match(parser, TOKEN_ELSE); AST* elseOp = ParseOperator(parser); AddASTChild(ifNode, elseOp); } return ifNode; }
AST* ParseLoad(ParserState* parser) { Match(parser, TOKEN_LOAD); return CreateASTNode(SEM_LOAD, Match(parser, TOKEN_STRING)); }
AST* ParseInclude(ParserState* parser) { Match(parser, TOKEN_INCLUDE); return CreateASTNode(SEM_INCLUDE, Match(parser, TOKEN_STRING)); }