Permalink
Browse files

Added field references and fixed calls

  • Loading branch information...
1 parent f10169a commit 9238306d73170596af89bbc15e13a067e5177064 @trishume committed Apr 9, 2012
View
1 include/TuringParser/ASTTokens.h
@@ -46,4 +46,5 @@ AST_TOKEN(BOOL_LITERAL) /* children: string: true or false */
AST_TOKEN(CALL) /* children: assignableExpr arg* string: */
AST_TOKEN(PTRDEREF) /* children: assignableExpr string: */
AST_TOKEN(FIELD_REF_OP) /* children: lhs string: rhs */
+AST_TOKEN(POINTER_FIELD_REF_OP) /* children: lhs string: rhs */
AST_TOKEN(VAR_REFERENCE) /* children: string: var name */
View
3 include/TuringParser/LexerTokens.h
@@ -3,6 +3,8 @@
TURING_TKN(COMMA,comma)
TURING_TKN(COLON,colon)
+TURING_TKN(HASH,hash)
+TURING_TKN(EXCLAMATION,exclamation point)
TURING_TKN(BRACKET_O,opening parenthesis)
TURING_TKN(BRACKET_C,closing parenthesis)
TURING_TKN(SQUARE_BRACKET_O,opening square bracket)
@@ -37,6 +39,7 @@ TURING_TKN(OP_GT,> operator)
TURING_TKN(OP_GE,>= operator)
TURING_TKN(OP_LT,< operator)
TURING_TKN(OP_LE,<= operator)
+TURING_TKN(OP_POINTER_FIELD_REF,-> operator)
TURING_TKN(OP_DOT,field reference operator)
TURING_TKN(DOTDOT,'..')
TURING_TKN(OP_AND,'and' operator)
View
6 include/TuringParser/ParseErrors.h
@@ -15,4 +15,8 @@ PARSE_ERROR(match_fail,"Expected %0; found %1.")
// args: unexpected token human name, unexpected token string
PARSE_ERROR(unexpected_token_in_expression,"Unexpected %0.")
// args: previous error, operator token human name
-PARSE_ERROR(possible_missing_op_rhs,"%0 Perhaps the other side of the %1 is missing?")
+PARSE_ERROR(possible_missing_op_rhs,"%0 In right side of %1.")
+// args:
+PARSE_ERROR(extra_comma_in_call,"Extra comma before the end of function call.")
+// args: human name of offending token
+PARSE_ERROR(no_identifier_in_field_ref,"%0 after field reference. Only identifiers can come after a field reference.")
View
3 include/TuringParser/Token.h
@@ -24,6 +24,9 @@ namespace OTParser {
SourceLoc getEnd() {
return Begin.advance(String.size());
}
+ SourceRange getRange() {
+ return SourceRange(Begin,getEnd());
+ }
//! \returns the name of a token. Or <UNKNOWN> for a bogus id.
static const char *getTokenName(Token::ID i);
View
11 include/TuringParser/TuringParser.h
@@ -20,7 +20,8 @@ namespace OTParser {
MULTIPLY, // *, /, div, mod, rem, shl, shr
PREFIX,
MODIFIER, // **, ^, #
- CALL // calling is an operator
+ CALL, // calling is an operator
+ FIELDREF
};
}
//! A pratt Expression Parser for Turing
@@ -66,6 +67,14 @@ namespace OTParser {
Token token);
virtual int getPrecedence(Parser *parser);
};
+ //! parses field reference operators that only take
+ //! identifiers as right hand sides
+ class FieldRefParselet : public InfixOp {
+ public:
+ virtual ASTNode *parse(Parser *parser, ASTNode *left,
+ Token token);
+ virtual int getPrecedence(Parser *parser);
+ };
//! parses binary operators that can use the short assign
//! syntax. I.E +/+= div/div= shl/shl=
/*class PossibleAssignBinOp : public InfixOp {
View
6 src/Lexer.cpp
@@ -181,6 +181,8 @@ namespace OTParser {
case '\'': return stringOrCharLiteral(true);
case ',': consume(); return newToken(Token::COMMA, ",");
+ case '#': consume(); return newToken(Token::HASH, "#");
+ case '!': consume(); return newToken(Token::EXCLAMATION, "!");
case '(': consume(); return newToken(Token::BRACKET_O, "(");
case ')': consume(); return newToken(Token::BRACKET_C, ")");
case '[': consume(); return newToken(Token::SQUARE_BRACKET_O, "[");
@@ -205,6 +207,10 @@ namespace OTParser {
return numLiteral();
}
consume(); // if it is not a number we can consume the -
+ if (C == '>') {
+ consume();
+ return newToken(Token::OP_POINTER_FIELD_REF, "->");
+ }
return newToken(Token::OP_MINUS, "-");
case '/':
consume();
View
2 src/Main.cpp
@@ -40,7 +40,7 @@ void testLexer(std::string fileName) {
int main(int argc, char** argv)
{
- SourceFile *f = new SourceFile("6*(7 + 4) - 7 div 6**6.0 < 8 xor 5 and true or false");
+ SourceFile *f = new SourceFile("6*(7 + 4) - Math.pow(7,9) div 6**6.0 < 8 xor variable.field->troll and true or false");
Lexer lex(f);
TuringParser parser(lex);
View
48 src/TuringParser.cpp
@@ -1,5 +1,7 @@
#include "TuringParser/TuringParser.h"
+#include "TuringParser/ParseError.h"
+
namespace OTParser {
TuringParser::TuringParser(Lexer lex) : Parser(lex) {
// -----------------------------------------------------------------
@@ -19,7 +21,8 @@ namespace OTParser {
// unary operators
registerPrefixOp(Token::OP_MINUS, new Parselet::UnaryOp(ASTNode::UNARY_OP));
registerPrefixOp(Token::OP_NOT, new Parselet::UnaryOp(ASTNode::UNARY_OP));
- registerPrefixOp(Token::OP_DEREF, new Parselet::UnaryOp(ASTNode::UNARY_OP));
+ registerPrefixOp(Token::HASH, new Parselet::UnaryOp(ASTNode::UNARY_OP)); // type cheat operator
+ registerPrefixOp(Token::OP_DEREF, new Parselet::UnaryOp(ASTNode::PTRDEREF));
// -----------------------------------------------------------------
// register the infix parselets: Binary and postfix operators, calls
// -----------------------------------------------------------------
@@ -54,6 +57,9 @@ namespace OTParser {
registerInfixOp(Token::OP_EXPONENT, op);
op = new Parselet::CallParselet();
registerInfixOp(Token::BRACKET_O, op);
+ op = new Parselet::FieldRefParselet();
+ registerInfixOp(Token::OP_DOT, op);
+ registerInfixOp(Token::OP_POINTER_FIELD_REF, op);
}
TuringParser::~TuringParser() {
@@ -94,16 +100,52 @@ namespace OTParser {
node->addChild(left); // TODO check for callable expression?
// we may have no arguments, so check for an immediate )
if (parser->curTok().Type != Token::BRACKET_C) {
- do {
+ node->addChild(parser->parseExpression()); // first argument
+ while (parser->curTok().Type == Token::COMMA) { // other args
+ parser->consume(); // consume comma
+ // extra comma like fun(hi,bob,)
+ if (parser->curTok().Type == Token::BRACKET_C) {
+ Token comma = parser->curTok();
+ ParseError err(comma.Begin,ParseError::extra_comma_in_call);
+ err.setEnd(comma.getEnd());
+ err.setHint(FixItHint::CreateRemoval(comma.getRange()));
+ throw err;
+ }
node->addChild(parser->parseExpression());
- } while (parser->curTok().Type == Token::COMMA);
+ }
}
parser->match(Token::BRACKET_C);
return node;
}
int CallParselet::getPrecedence(Parser *parser) {
return Precedence::CALL;
}
+ ASTNode *FieldRefParselet::parse(Parser *parser, ASTNode *left, Token token) {
+ ASTNode *node = new ASTNode(ASTNode::FIELD_REF_OP,token.Begin);
+ bool isPointerRef = (token.Type == Token::OP_POINTER_FIELD_REF);
+
+ // TODO check for field reffable LHS?
+ if (isPointerRef) { // cheat, h->b is equivelant to ^h.b
+ ASTNode *deref = new ASTNode(ASTNode::PTRDEREF,token.Begin);
+ deref->addChild(left);
+ node->addChild(deref);
+ } else {
+ node->addChild(left);
+ }
+
+ Token tok = parser->consume();
+ if (tok.Type != Token::IDENTIFIER) {
+ ParseError err(tok.Begin,ParseError::no_identifier_in_field_ref);
+ err << Token::getHumanTokenName(tok.Type);
+ err.setEnd(tok.getEnd());
+ throw err;
+ }
+ node->str = tok.String; // field name
+ return node;
+ }
+ int FieldRefParselet::getPrecedence(OTParser::Parser *parser) {
+ return Precedence::FIELDREF;
+ }
/* Turing does not allow assignment as an expression but you can uncomment this and
use it if you want them.
ASTNode *PossibleAssignBinOp::parse(Parser *parser, ASTNode *left, Token token) {

0 comments on commit 9238306

Please sign in to comment.