private ICodeNode ParseSimpleExpression(Token token) { TokenType signType = null; // type of leading sign (if any) // Look for a leading + or - sign. TokenType tokenType = token.type; if ((tokenType == PascalTokenType.PLUS) || (tokenType == PascalTokenType.MINUS)) { signType = tokenType; token = NextToken(); // consume the + or - } // Parse a term and make the root of its tree the root node. ICodeNode rootNode = ParseTerm(token); // Was there a leading - sign? if (signType == PascalTokenType.MINUS) { // Create a NEGATE node and adopt the current tree // as its child. The NEGATE node becomes the new root node. ICodeNode negateNode = ICodeFactory.CreateICodeNode(ICodeNodeTypeImplementation.NEGATE); negateNode.AddChild(rootNode); rootNode = negateNode; } token = CurrentToken(); tokenType = token.type; // Loop over additive operators. while (ADD_OPS.Contains(tokenType)) { // Create a new operator node and adopt the current tree // as its first child. ICodeNodeType nodeType = ADD_OPS_OPS_MAP[(PascalTokenType)tokenType]; ICodeNode opNode = ICodeFactory.CreateICodeNode(nodeType); opNode.AddChild(rootNode); token = NextToken(); // consume the operator // Parse another term. The operator node adopts // the term's tree as its second child. opNode.AddChild(ParseTerm(token)); // The operator node becomes the new root node. rootNode = opNode; token = CurrentToken(); tokenType = token.type; } return(rootNode); }
// Parse a statement list. protected internal void ParseList(Token token, ICodeNode parentNode, PascalTokenType terminator, PascalErrorCode errorCode) { // Loop to parse each statement until the END token or the end of the source file. while (!(token is EofToken) && (token.type != terminator)) { // Parse a statement. The parent node adopts the statement node. ICodeNode statementNode = Parse(token); parentNode.AddChild(statementNode); token = CurrentToken(); TokenType tokenType = token.type; // Look for semicolon between statements. if (tokenType == PascalTokenType.SEMICOLON) token = NextToken(); // If at the start of the next assignment statement, then missing a semicolon. else if (tokenType == PascalTokenType.IDENTIFIER) errorHandler.flag(token, PascalErrorCode.MISSING_SEMICOLON, this); else if (tokenType != terminator) { errorHandler.flag(token, PascalErrorCode.UNEXPECTED_TOKEN, this); token = NextToken(); } } if (token.type == terminator) token = NextToken(); else errorHandler.flag(token, errorCode, this); }
private ICodeNode ParseExpression(Token token) { ICodeNode rootNode = ParseSimpleExpression(token); token = CurrentToken(); PascalTokenType tokenType = (PascalTokenType)token.type; // TokenType in original Java // Look for relational operator if (REL_OPS.Contains(tokenType)) { // Create a new operator node and adopt the current tree as its first child. ICodeNodeType nodeType = REL_OPS_MAP[tokenType]; ICodeNode opNode = ICodeFactory.CreateICodeNode(nodeType); opNode.AddChild(rootNode); token = NextToken(); opNode.AddChild(ParseSimpleExpression(token)); rootNode = opNode; } return(rootNode); }
public override ICodeNode Parse(Token token) { // Create the ASSIGN node. ICodeNode assignNode = ICodeFactory.CreateICodeNode(ICodeNodeTypeImplementation.ASSIGN); string targetName = token.text.ToLower(); SymbolTableEntry targetID = symbolTableStack.Lookup(targetName); if (targetID == null) { targetID = symbolTableStack.EnterLocal(targetName); } targetID.AppendLineNumber(token.lineNumber); token = NextToken(); ICodeNode variableNode = ICodeFactory.CreateICodeNode(ICodeNodeTypeImplementation.VARIABLE); variableNode.SetAttribute(ICodeKeyImplementation.ID, targetID); assignNode.AddChild(variableNode); if (token.type == PascalTokenType.COLON_EQUALS) { token = NextToken(); } else { errorHandler.flag(token, PascalErrorCode.MISSING_COLON_EQUALS, this); } ExpressionParser expressionParser = new ExpressionParser(this); assignNode.AddChild(expressionParser.Parse(token)); return(assignNode); }
private ICodeNode ParseTerm(Token token) { ICodeNode rootNode = ParseFactor(token); token = CurrentToken(); TokenType tokenType = token.type; while (MULT_OPS.Contains(tokenType)) { ICodeNodeType nodeType = MULT_OPS_OPS_MAP[(PascalTokenType)tokenType]; ICodeNode opNode = ICodeFactory.CreateICodeNode(nodeType); opNode.AddChild(rootNode); token = NextToken(); // consume the operator opNode.AddChild(ParseFactor(token)); rootNode = opNode; token = CurrentToken(); tokenType = token.type; } return(rootNode); }
// Parse a statement list. protected internal void ParseList(Token token, ICodeNode parentNode, PascalTokenType terminator, PascalErrorCode errorCode) { // Loop to parse each statement until the END token or the end of the source file. while (!(token is EofToken) && (token.type != terminator)) { // Parse a statement. The parent node adopts the statement node. ICodeNode statementNode = Parse(token); parentNode.AddChild(statementNode); token = CurrentToken(); TokenType tokenType = token.type; // Look for semicolon between statements. if (tokenType == PascalTokenType.SEMICOLON) { token = NextToken(); } // If at the start of the next assignment statement, then missing a semicolon. else if (tokenType == PascalTokenType.IDENTIFIER) { errorHandler.flag(token, PascalErrorCode.MISSING_SEMICOLON, this); } else if (tokenType != terminator) { errorHandler.flag(token, PascalErrorCode.UNEXPECTED_TOKEN, this); token = NextToken(); } } if (token.type == terminator) { token = NextToken(); } else { errorHandler.flag(token, errorCode, this); } }
public void ParseList(Token token, ref ICodeNode parent, ILangTokenType terminator, ILangErrorCode error) { // As long as we are parseing neither endToken or terminating token // do this while (!(token is EndOfFileToken) && (token.TokenType.ToString() != terminator.ToString())) { ICodeNode statementNode = Parse(token); parent.AddChild(statementNode); // token have been moved; get the latest token = CurrentToken(); if (token.TokenType == "semicolon") { token = NextToken(); // move beyond the statement separator. } else if (token.TokenType == "identifier") { ErrorHandler.Singleton.Flag(token, "missing_semicolon", this); } else if (token.TokenType != terminator) { ErrorHandler.Singleton.Flag(token, "unexpected_token", this); token = NextToken(); } } if (token.TokenType == terminator) { token = NextToken(); } else { ErrorHandler.Singleton.Flag(token, error, this); } }
private ICodeNode ParseFactor(Token token) { TokenType tokenType = token.type; ICodeNode rootNode = null; switch (tokenType.ToString()) { case "IDENTIFIER": { // Look up the identifier in the symbol table stack. // Flag the identifier as undefined if it's not found. String name = token.text.ToLower(); SymbolTableEntry id = symbolTableStack.Lookup(name); if (id == null) { errorHandler.flag(token, PascalErrorCode.IDENTIFIER_UNDEFINED, this); id = symbolTableStack.EnterLocal(name); } rootNode = ICodeFactory.CreateICodeNode(ICodeNodeTypeImplementation.VARIABLE); rootNode.SetAttribute(ICodeKeyImplementation.ID, id); id.AppendLineNumber(token.lineNumber); token = NextToken(); // consume the identifier break; } case "INTEGER": { // Create an INTEGER_CONSTANT node as the root node. rootNode = ICodeFactory.CreateICodeNode(ICodeNodeTypeImplementation.INTEGER_CONSTANT); rootNode.SetAttribute(ICodeKeyImplementation.VALUE, token.value); token = NextToken(); // consume the number break; } case "REAL": { // Create an REAL_CONSTANT node as the root node. rootNode = ICodeFactory.CreateICodeNode(ICodeNodeTypeImplementation.REAL_CONSTANT); rootNode.SetAttribute(ICodeKeyImplementation.VALUE, token.value); token = NextToken(); // consume the number break; } case "STRING": { String value = (String)token.value; // Create a STRING_CONSTANT node as the root node. rootNode = ICodeFactory.CreateICodeNode(ICodeNodeTypeImplementation.STRING_CONSTANT); rootNode.SetAttribute(ICodeKeyImplementation.VALUE, value); token = NextToken(); // consume the string break; } case "NOT": { token = NextToken(); // consume the NOT // Create a NOT node as the root node. rootNode = ICodeFactory.CreateICodeNode(ICodeNodeTypeImplementation.NOT); // Parse the factor. The NOT node adopts the // factor node as its child. rootNode.AddChild(ParseFactor(token)); break; } case "LEFT_PAREN": { token = NextToken(); // consume the ( // Parse an expression and make its node the root node. rootNode = ParseExpression(token); // Look for the matching ) token. token = CurrentToken(); if (token.type == PascalTokenType.RIGHT_PAREN) { token = NextToken(); // consume the ) } else { errorHandler.flag(token, PascalErrorCode.MISSING_RIGHT_PAREN, this); } break; } default: { errorHandler.flag(token, PascalErrorCode.UNEXPECTED_TOKEN, this); break; } } return(rootNode); }