REL_OPS_SET // Set of terminal symbols representing relational operators
EXP_OPS_SET // SET containing PLUS and MINUS
TERM_OPS_SET // Set containing TIMES and DIVIDE
RelCondition
/**
* RelCondition -> Exp [ RelOp Exp ]
*/
void parseRelCondition() {
parseExp();
if (tokens.isIn(REL_OPS_SET)) {
parseRelOp(); // This cannot fail, as we know that the current token can start a RelOp
parseExp();
}
}
Expression
/**
* Exp -> [PLUS | MINUS] Term {(PLUS | MINUS) Term}
*/
void parseExp() {
// Match the optional PLUS or MINUS
if (tokens.isMatch(Token.PLUS)) {
// This cannot fail, as we know the current token is Token.PLUS
tokens.match(Token.PLUS); // Consume and move to the next token.
} else if (tokens.isMatch(Token.MINUS)) {
// Cannot fail, for the same reason as above.
tokens.match(Token.MINUS); // Consume and move to the next token.
}
parseTerm();
// Parse the repetition construct
while (tokens.isIn(EXP_OPS_SET)) {
// While token is PLUS or MINUS
if (tokens.isMatch(Token.PLUS)) { tokens.match(Token.PLUS)}
else if (tokens.isMatch(Token.MINUS)) { tokens.match(Token.MINUS)}
else {
// Unreachable because of the guard (condition) of the while loop
fatal("Internal error in parseExp")
}
parseTerm();
}
}
Term
/**
* Term -> Factor {(TIMES | DIVIDE) Factor}
*/
void parseTerm() {
parseFactor();
// Parse the optional times or divide
// Parse the repetition construct
while (tokens.isIn(EXP_OPS_SET)) {
// While token is PLUS or MINUS
if (tokens.isMatch(Token.PLUS)) { tokens.match(Token.PLUS)}
else if (tokens.isMatch(Token.MINUS)) { tokens.match(Token.MINUS)}
else {
// Unreachable because of the guard (condition) of the while loop
fatal("Internal error in parseExp")
}
parseTerm();
}
}
Factor
/**
* Factor -> LPAREN RelCondition RPAREN | NUMBER | LValue
*/
void parseFactor() {
if (tokens.isMatch(Token.LPAREN)) {
// First alternatives
tokens.match(Token.LPAREN); // Cannot fail.
parseRelCondition();
tokens.match(Token.RPAREN); // THIS CAN FAIL!
} else if (tokens.isMatch(Token.NUMBER)) {
tokens.match(Token.NUMBER); // Cannot fail.
} else if (tokens.isMatch(Token.IDENTIFIER)) {
parseLValue();
} else {
errors.error("Syntax error");
}
}
RelOp
/**
* RelOp -> EQUALS | NEQUALS | LEQUALS | LESS | GREATER | GEQUALS
*/
void parseRelOp() {
if (tokens.isMatch(Token.EQUALS)) {
tokens.match(Token.EQUALS);
} else if (tokens.isMatch(Token.NEQUALS)) {
tokens.match(Token.NEQUALS);
} else if (tokens.isMatch(Token.LEQUALS)) {
tokens.match(Token.LEQUALS);
} else if (tokens.isMatch(Token.LESS)) {
tokens.match(Token.LESS);
} else if (tokens.isMatch(Token.GREATER)) {
tokens.match(Token.GREATER);
} else if (tokens.isMatch(Token.GEQUALS)) {
tokens.match(Token.GEQUALS);
} else {
// Error
errors.error("Syntax error: ...");
}
}
LValue
void parseLValue() {
tokens.match(Token.IDENTIFIER);
}