RelCondition

CourseCompilers & Interpreters
SemesterS1 2022
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);
}