private void LexChar(char characterToMatch, Token context) { int characterInt = PeekChar(); if (characterInt == -1) { return; } char character = (char)characterInt; if (character != characterToMatch) { throw UnexpectedCharException.Create(character, context, characterToMatch); } AdvanceChar(); }
public Lexeme <Token> LexOne() { int characterInt; char character; Start: do { characterInt = AdvanceChar(); if (characterInt == -1) { return(MakeLexeme(Token.EoF)); } character = (char)characterInt; }while (char.IsWhiteSpace(character)); if (character == '/' && PeekChar() == '/') { characterInt = AdvanceChar(); while (characterInt != -1 && characterInt != '\n') { characterInt = AdvanceChar(); } if (characterInt == -1) { return(MakeLexeme(Token.EoF)); } goto Start; } TokenBuffer.Append(character); switch (character) { case '+': return(MakeLexeme(SwitchOnNextCharacter( Token.Add, ('+', Token.Increment), ('=', Token.AddCompoundAssign)))); case '-': return(MakeLexeme(SwitchOnNextCharacter( Token.Subtract, ('-', Token.Decrement), ('=', Token.SubtractCompoundAssign)))); case '*': return(MakeLexeme(SwitchOnNextCharacter( Token.Multiply, ('=', Token.MultiplyCompoundAssign)))); case '/': return(MakeLexeme(SwitchOnNextCharacter( Token.Divide, ('=', Token.DivideCompoundAssign)))); case '%': return(MakeLexeme(SwitchOnNextCharacter( Token.Remainder, ('=', Token.RemainderCompoundAssign)))); case '!': return(MakeLexeme( SwitchOnNextCharacter(Token.LogicalNot, ('=', Token.ComparisonNotEqual)))); case '~': return(MakeLexeme( Token.BitwiseNot)); case '^': return(MakeLexeme(SwitchOnNextCharacter( Token.BitwiseXor, ('=', Token.BitwiseXorCompoundAssign)))); case '=': return(MakeLexeme(SwitchOnNextCharacter( Token.Assign, ('=', Token.ComparisonEqual), ('>', Token.Arrow)))); case ':': return(MakeLexeme(SwitchOnNextCharacter( Token.Colon, (':', Token.StaticAccessor)))); case '&': var andType = SwitchOnNextCharacter( Token.BitwiseAnd, ('=', Token.BitwiseAndCompoundAssign), ('&', Token.LogicalAnd)); if (andType == Token.LogicalAnd) { andType = SwitchOnNextCharacter( Token.LogicalAnd, ('=', Token.LogicalAndCompoundAssign)); } return(MakeLexeme(andType)); case '|': var orType = SwitchOnNextCharacter( Token.BitwiseOr, ('=', Token.BitwiseOrCompoundAssign), ('|', Token.LogicalOr)); if (orType == Token.LogicalOr) { orType = SwitchOnNextCharacter( Token.LogicalOr, ('=', Token.LogicalOrCompoundAssign)); } return(MakeLexeme(orType)); case '<': var lessType = SwitchOnNextCharacter( Token.ComparisonLessThan, ('=', Token.ComparisonLessThanOrEqual), ('-', Token.ReferenceAssign), ('<', Token.BitshiftLeft)); if (lessType == Token.BitshiftLeft) { lessType = SwitchOnNextCharacter( Token.BitshiftLeft, ('=', Token.BitshiftLeftCompoundAssign)); } return(MakeLexeme(lessType)); case '>': var greaterType = SwitchOnNextCharacter( Token.ComparisonGreaterThan, ('=', Token.ComparisonGreaterThanOrEqual), ('>', Token.BitshiftRight)); if (greaterType == Token.BitshiftRight) { greaterType = SwitchOnNextCharacter( Token.BitshiftRight, ('=', Token.BitshiftRightCompoundAssign)); } return(MakeLexeme(greaterType)); case '\'': LexEscapableChar(Token.CharacterLiteral); LexChar('\'', Token.CharacterLiteral); return(MakeLexeme(Token.CharacterLiteral)); case '\"': while (true) { int nextCharacterInt = PeekChar(); if (nextCharacterInt == -1) { throw UnexpectedCharException.Create(null, Token.StringLiteral, "a char or a string delimiter"); } char nextCharacter = (char)nextCharacterInt; if (nextCharacter == '\"') { AdvanceChar(); TokenBuffer.Append(nextCharacter); break; } LexEscapableChar(Token.StringLiteral); } return(MakeLexeme(Token.StringLiteral)); case '{': return(MakeLexeme(Token.LBraces)); case '}': return(MakeLexeme(Token.RBraces)); case '[': return(MakeLexeme(Token.LBrackets)); case ']': return(MakeLexeme(Token.RBrackets)); case '(': return(MakeLexeme(Token.LParens)); case ')': return(MakeLexeme(Token.RParens)); case ';': return(MakeLexeme(Token.Semicolon)); case '?': return(MakeLexeme(Token.QuestionMark)); case ',': return(MakeLexeme(Token.Comma)); } // Identifier or keyword if (char.IsLetter(character) || character == '_') { while (true) { int nextCharacterInt = PeekChar(); if (nextCharacterInt == -1) { break; } char nextCharacter = (char)nextCharacterInt; if (!char.IsLetterOrDigit(nextCharacter) && nextCharacter != '_') { break; } AdvanceChar(); TokenBuffer.Append(nextCharacter); } return(MakeLexeme(_keywords.TryGetValue(TokenBuffer.ToString(), out Token keyword) ? keyword : Token.Identifier)); } // Numerical literal { bool reachedDot = false; if (character == '.') { reachedDot = true; int nextCharacterInt = PeekChar(); if (nextCharacterInt == -1) { throw UnexpectedCharException.Create(null, Token.FloatLiteral, "Digit"); } character = (char)nextCharacterInt; if (!char.IsDigit(character)) { return(MakeLexeme(Token.Accessor)); //throw UnexpectedCharException.Create(character, Token.FloatLiteral, "Digit"); } } if (char.IsDigit(character)) { LexNumber(ref reachedDot); return(reachedDot ? MakeLexeme(Token.FloatLiteral) : MakeLexeme(Token.IntegerLiteral)); } } throw UnexpectedCharException.Create(character, Token.EoF, "EoF"); }