RT,代码有点长~~,忍一下~~
enum class TokenType
{
NUMBER = 3,
PLUS,
MINUS,
MULTIPLY,
DIVIDE,
MOD,
EQUAL,
NOT_EQUAL,
LESS_THAN,
LESS_THAN_OR_EQUAL,
GREATER_THAN,
GREATER_THAN_OR_EQUAL,
LOGICAL_AND,
LOGICAL_OR,
BITWISE_AND,
BITWISE_OR,
BITWISE_XOR,
BITWISE_NOT,
LEFT_SHIFT,
RIGHT_SHIFT,
INCREMENT,
DECREMENT,
PLUS_ASSIGN,
MINUS_ASSIGN,
MULTIPLY_ASSIGN,
DIVIDE_ASSIGN,
MOD_ASSIGN,
BITWISE_AND_ASSIGN,
BITWISE_OR_ASSIGN,
BITWISE_XOR_ASSIGN,
LEFT_SHIFT_ASSIGN,
RIGHT_SHIFT_ASSIGN,
LOGICAL_NOT,
LOGICAL_NOT_ASSIGN,
LPAREN,
RPAREN,
LBRACE,
RBRACE,
LSQUARE,
RSQUARE,
COMMA,
SEMICOLON,
COLON,
DOT,
ARROW,
ELLIPSIS,
QUESTION,
INDENT,
KEYWORD,
IDENTIFIER,
COMMENTLINE,
PREPROCESSOR,
CONNECT,
STRING,
CHARACTER,
END
};
#include <iostream>
#include <string>
#include <cctype>
#include <unordered_set>
#include <stdexcept>
using namespace std;
struct Token
{
TokenType type;
string value;
Token(){}
Token(TokenType type, string value) : type(type), value(value) {}
};
class Lexer
{
public:
Lexer(string input) : input(input), currentPos(0)
{
keywords = {"if", "else", "while", "for", "int", "float", "void", "return", "class", "struct", "namespace", "const", "static", "public", "private", "protected", "friend", "virtual", "override", "final", "template", "typename", "using", "new", "delete", "try", "catch", "throw", "sizeof"}; // 关键字集合
}
Token getNextToken()
{
while (currentPos < input.length())
{
char currentChar = input[currentPos];
if (isspace(currentChar))
{
if (currentChar == '\t') // 判断是否为缩进符号
{
currentPos++;
return Token{TokenType::INDENT, "\\t"};
}
currentPos++;
continue;
}
if (isdigit(currentChar))
{
string number = getNumber();
return Token{TokenType::NUMBER, number};
}
else if (isalpha(currentChar) || currentChar == '_')
{
return isKeywordOrIdentifier();
}
else
{
string str;
switch (currentChar)
{
case '+':
if (input[currentPos + 1] == '=')
{
currentPos += 2;
return Token{TokenType::INCREMENT, "+="};
}
currentPos++;
return Token{TokenType::PLUS, "+"};
case '-':
if (input[currentPos + 1] == '>')
{
currentPos += 2;
return Token{TokenType::ARROW, "->"};
}
if (input[currentPos + 1] == '=')
{
currentPos += 2;
return Token{TokenType::DECREMENT, "-="};
}
currentPos++;
return Token{TokenType::MINUS, "-"};
case '#':
if (input[currentPos + 1] == '#')
{
currentPos += 2;
return Token{TokenType::CONNECT, "##"};
}
currentPos++;
return Token{TokenType::PREPROCESSOR, "#"};
case '(':
currentPos++;
return Token{TokenType::LPAREN, "("};
case ')':
currentPos++;
return Token{TokenType::RPAREN, ")"};
case '[':
currentPos++;
return Token{TokenType::LSQUARE, "["};
case ']':
currentPos++;
return Token{TokenType::RSQUARE, "]"};
case '{':
currentPos++;
return Token{TokenType::LBRACE, "{"};
case '}':
currentPos++;
return Token{TokenType::RBRACE, "}"};
case ':':
currentPos++;
return Token{TokenType::COLON, ":"};
case ';':
currentPos++;
return Token{TokenType::SEMICOLON, ";"};
case '.':
currentPos++;
return Token{TokenType::DOT, "."};
case '"':
currentPos++;
str = input.substr(currentPos, input.substr(currentPos).find_first_of('"') - currentPos + 1);
return Token{TokenType::STRING, str};
case '?':
currentPos++;
return Token{TokenType::QUESTION, "?"};
case '*':
if (input[currentPos + 1] == '=')
{
currentPos += 2;
return Token{TokenType::MULTIPLY_ASSIGN, "*="};
}
currentPos++;
return Token{TokenType::MULTIPLY, "*"};
case '/':
if (input[currentPos + 1] == '=')
{
currentPos += 2;
return Token{TokenType::DIVIDE_ASSIGN, "/="};
}
if (input[currentPos + 1] == '/')
{
currentPos += 2;
return Token{TokenType::COMMENTLINE, "//"};
}
currentPos++;
return Token{TokenType::DIVIDE, "/"};
case '%':
if (input[currentPos + 1] == '=')
{
currentPos += 2;
return Token{TokenType::MOD_ASSIGN, "%="};
}
currentPos++;
return Token{TokenType::MOD, "%"};
case '=':
if (input[currentPos + 1] == '=')
{
currentPos += 2;
return Token{TokenType::EQUAL, "=="};
}
currentPos++;
return Token{TokenType::EQUAL, "="};
case '!':
if (input[currentPos + 1] == '=')
{
currentPos += 2;
return Token{TokenType::NOT_EQUAL, "!="};
}
currentPos++;
return Token{TokenType::LOGICAL_NOT, "!"};
case '<':
if (input[currentPos + 1] == '=')
{
currentPos += 2;
return Token{TokenType::LESS_THAN_OR_EQUAL, "<="};
}
if (input[currentPos + 1] == '<')
{
if (input[currentPos + 2] == '=')
{
currentPos += 3;
return Token{TokenType::LEFT_SHIFT_ASSIGN, "<<="};
}
currentPos += 2;
return Token{TokenType::LEFT_SHIFT, "<<"};
}
currentPos++;
return Token{TokenType::LESS_THAN, "<"};
case '>':
if (input[currentPos + 1] == '>')
{
if (input[currentPos + 2] == '=')
{
currentPos += 3;
return Token{TokenType::RIGHT_SHIFT_ASSIGN, ">>="};
}
currentPos += 2;
return Token{TokenType::RIGHT_SHIFT, ">>"};
}
if (input[currentPos + 1] == '=')
{
currentPos += 2;
return Token{TokenType::GREATER_THAN_OR_EQUAL, ">="};
}
currentPos++;
return Token{TokenType::GREATER_THAN, ">"};
// 添加更多运算符的识别代码
case '&':
if (input[currentPos + 1] == '&')
{
currentPos += 2;
return Token{TokenType::LOGICAL_AND, "&&"};
}
if (input[currentPos + 1] == '=')
{
currentPos += 2;
return Token{TokenType::BITWISE_AND_ASSIGN, "&="};
}
currentPos++;
return Token{TokenType::BITWISE_AND, "&"};
case '|':
if (input[currentPos + 1] == '|')
{
currentPos += 2;
return Token{TokenType::LOGICAL_OR, "||"};
}
if (input[currentPos + 1] == '=')
{
currentPos += 2;
return Token{TokenType::BITWISE_OR_ASSIGN, "|="};
}
currentPos++;
return Token{TokenType::BITWISE_OR, "|"};
case '^':
if (input[currentPos + 1] == '=')
{
currentPos += 2;
return Token{TokenType::BITWISE_XOR_ASSIGN, "^="};
}
currentPos++;
return Token{TokenType::BITWISE_XOR, "^"};
case '~':
currentPos++;
return Token{TokenType::BITWISE_NOT, "~"};
default:
throw runtime_error("Invalid character");
}
}
}
return Token{TokenType::END, ""};
}
string getNumber()
{
string number;
while (currentPos < input.length() && isdigit(input[currentPos]))
{
number += input[currentPos];
currentPos++;
}
return number;
}
Token isKeywordOrIdentifier()
{
string word;
while (currentPos < input.length() && (isalnum(input[currentPos]) || input[currentPos] == '_' || input[currentPos] == '$'))
{
word += input[currentPos];
currentPos++;
}
if (keywords.find(word) != keywords.end())
{
return Token{TokenType::KEYWORD, word};
}
else
{
return Token{TokenType::IDENTIFIER, word};
}
}
private:
string input;
size_t currentPos;
unordered_set<string> keywords;
};
class Node
{
public:
char op;
int value;
Node* left;
Node* right;
Node(char op, int value = 0, Node* left = nullptr, Node* right = nullptr) : op(op), value(value), left(left), right(right) {}
};
class Parser
{
public:
Parser(Lexer& lexer) : lexer(lexer), currentToken(lexer.getNextToken()) {}
void eat(TokenType tokenType)
{
if (currentToken.type == tokenType)
{
currentToken = lexer.getNextToken();
}
else
{
throw runtime_error("Syntax error: Unexpected token");
}
}
Node* factor()
{
Token token = lexer.getNextToken();
if (token.type == TokenType::NUMBER)
{
return new Node('\0', stoi(token.value));
}
else if (token.type == TokenType::LPAREN)
{
Node* node = expr();
lexer.getNextToken();
return node;
}
return nullptr;
}
Node* term()
{
Node* node = factor();
while (currentToken.type == TokenType::MULTIPLY || currentToken.type == TokenType::DIVIDE)
{
Token op = currentToken;
eat(op.type);
Node* right = factor();
node = new Node(op.value[0], 0, node, right);
}
return node;
}
Node* expr()
{
Node* node = term();
while (currentToken.type == TokenType::PLUS || currentToken.type == TokenType::MINUS)
{
Token op = currentToken;
eat(op.type);
Node* right = term();
node = new Node(op.value[0], 0, node, right);
}
return node;
}
private:
Lexer& lexer;
Token currentToken;
};
int eval(Node* node)
{
if (node == nullptr)
{
return 0;
}
cout << node->op << ' ' << node->value << endl;
if (node->op == '\0') // Leaf node
{
return node->value;
}
int leftValue = eval(node->left);
int rightValue = eval(node->right);
switch (node->op)
{
case '+':
return leftValue + rightValue;
case '-':
return leftValue - rightValue;
case '*':
return leftValue * rightValue;
case '/':
if (rightValue == 0)
{
throw runtime_error("Division by zero");
}
return leftValue / rightValue;
default:
throw runtime_error("Invalid operator");
}
}
int main()
{
string input;
getline(cin, input);
Lexer lexer(input);
Token token;
do
{
token = lexer.getNextToken();
cout << "Token: " << (int)token.type << ' ' << token.value << endl;
} while (token.type != TokenType::END);
Parser p(lexer);
cout << eval(p.expr()) << endl;
return 0;
}