SmartPointer<Entity> Parser::quotedExpr(Tokenizer &tokenizer) { ParseScope scope(tokenizer.getScanner()); tokenizer.match(TokenType::OBRACKET_TOKEN); SmartPointer<Entity> expr = expression(tokenizer); tokenizer.match(TokenType::CBRACKET_TOKEN); return scope.set(new QuotedExpr(expr)); }
SmartPointer<Entity> Parser::reference(Tokenizer &tokenizer) { ParseScope scope(tokenizer.getScanner()); tokenizer.match(TokenType::POUND_TOKEN); if (tokenizer.consume(TokenType::OANGLE_TOKEN)) { string id = tokenizer.match(TokenType::ID_TOKEN).getValue(); tokenizer.match(TokenType::CANGLE_TOKEN); return scope.set(new NamedReference(id)); } else return scope.set(new Reference(numberRefOrExpr(tokenizer))); }
SmartPointer<Number> Parser::number(Tokenizer &tokenizer) { ParseScope scope(tokenizer.getScanner()); double value = String::parseDouble(tokenizer.match(TokenType::NUMBER_TOKEN).getValue()); return scope.set(new Number(value)); }
SmartPointer<Assign> Parser::assign(Tokenizer &tokenizer) { ParseScope scope(tokenizer.getScanner()); SmartPointer<Entity> ref = reference(tokenizer); tokenizer.match(TokenType::ASSIGN_TOKEN); return scope.set(new Assign(ref, expression(tokenizer))); }
SmartPointer<Word> Parser::word(Tokenizer &tokenizer) { ParseScope scope(tokenizer.getScanner()); string name = tokenizer.match(TokenType::ID_TOKEN).getValue(); if (name.length() != 1) THROWS("Invalid word '" << name << "'"); return scope.set(new Word(toupper(name[0]), numberRefOrExpr(tokenizer))); }
SmartPointer<Comment> Parser::comment(Tokenizer &tokenizer) { ParseScope scope(tokenizer.getScanner()); Token token; bool paren = tokenizer.getType() == TokenType::PAREN_COMMENT_TOKEN; if (paren) token = tokenizer.advance(); else token = tokenizer.match(TokenType::COMMENT_TOKEN); return scope.set(new Comment(token.getValue(), paren)); }
SmartPointer<OCode> Parser::ocode(Tokenizer &tokenizer) { ParseScope scope(tokenizer.getScanner()); tokenizer.match(TokenType::ID_TOKEN); // The 'O' SmartPointer<OCode> ocode; if (tokenizer.isType(TokenType::OANGLE_TOKEN)) { tokenizer.match(TokenType::OANGLE_TOKEN); string name = tokenizer.match(TokenType::ID_TOKEN).getValue(); tokenizer.match(TokenType::CANGLE_TOKEN); string keyword = tokenizer.match(TokenType::ID_TOKEN).getValue(); ocode = new OCode(String::toLower(name), keyword); } else { SmartPointer<Entity> numExpr = numberRefOrExpr(tokenizer); string keyword = tokenizer.match(TokenType::ID_TOKEN).getValue(); ocode = new OCode(numExpr, keyword); } while (tokenizer.isType(TokenType::OBRACKET_TOKEN)) ocode->addExpression(quotedExpr(tokenizer)); scope.set(ocode->getLocation()); return ocode; }
SmartPointer<FunctionCall> Parser::functionCall(Tokenizer &tokenizer) { ParseScope scope(tokenizer.getScanner()); string name = tokenizer.match(TokenType::ID_TOKEN).getValue(); SmartPointer<Entity> arg1 = quotedExpr(tokenizer); SmartPointer<Entity> arg2; // Special case if (String::toUpper(name) == "ATAN" && tokenizer.consume(TokenType::DIV_TOKEN)) arg2 = quotedExpr(tokenizer); return scope.set(new FunctionCall(name, arg1, arg2)); }
SmartPointer<Block> Parser::block(Tokenizer &tokenizer) { ParseScope scope(tokenizer.getScanner()); // Deleted bool deleted = false; if (tokenizer.consume(TokenType::DIV_TOKEN)) deleted = true; // Line number int line = -1; if (tokenizer.isID("N")) { tokenizer.advance(); Token num = tokenizer.match(TokenType::NUMBER_TOKEN); line = String::parseU32(num.getValue()); } // Children std::vector<SmartPointer<Entity> > children; // O-Code if (tokenizer.isID("O")) children.push_back(ocode(tokenizer)); while (tokenizer.hasMore()) { switch (tokenizer.getType()) { case TokenType::EOL_TOKEN: break; // End of block case TokenType::COMMENT_TOKEN: case TokenType::PAREN_COMMENT_TOKEN: children.push_back(comment(tokenizer)); break; case TokenType::POUND_TOKEN: children.push_back(assign(tokenizer)); break; default: if (!tokenizer.isType(TokenType::ID_TOKEN)) THROWS("Expected word or assignment, found " << tokenizer.getType()); children.push_back(word(tokenizer)); break; } if (tokenizer.getType() == TokenType::EOL_TOKEN) { tokenizer.advance(); break; } } return scope.set(new Block(deleted, line, children)); }