用C++设计LL(1)简单算数表达式语法分析器,输入为x+y*(3*a+7)-b/5,输出为TRUE
时间: 2023-12-03 18:45:36 浏览: 105
首先,我们需要将算术表达式转换成一个语法树,然后通过遍历语法树来判断表达式是否合法。LL(1)分析算法可以用来构建语法树,下面是一个简单的C++实现。
首先,我们需要定义一个Token类来表示算术表达式中的各个token:
```
class Token {
public:
enum TokenType {
PLUS, MINUS, TIMES, DIVIDE, LPAREN, RPAREN, ID, NUM, EOI, ERROR
};
Token(TokenType type, std::string value = "") : m_type(type), m_value(value) {}
TokenType getType() const { return m_type; }
std::string getValue() const { return m_value; }
private:
TokenType m_type;
std::string m_value;
};
```
然后,我们需要定义一个词法分析器,用来将算术表达式转换成Token序列:
```
class Lexer {
public:
Lexer(const std::string& input) : m_input(input), m_pos(0) {}
Token getNextToken() {
while (m_pos < m_input.length()) {
char c = m_input[m_pos++];
if (isspace(c)) {
continue;
}
if (isdigit(c)) {
std::string value;
value += c;
while (m_pos < m_input.length() && isdigit(m_input[m_pos])) {
value += m_input[m_pos++];
}
return Token(Token::NUM, value);
}
if (isalpha(c)) {
std::string value;
value += c;
while (m_pos < m_input.length() && isalnum(m_input[m_pos])) {
value += m_input[m_pos++];
}
return Token(Token::ID, value);
}
switch (c) {
case '+': return Token(Token::PLUS);
case '-': return Token(Token::MINUS);
case '*': return Token(Token::TIMES);
case '/': return Token(Token::DIVIDE);
case '(': return Token(Token::LPAREN);
case ')': return Token(Token::RPAREN);
}
}
return Token(Token::EOI);
}
private:
std::string m_input;
size_t m_pos;
};
```
接下来,我们需要定义一个语法分析器,用来构建语法树并检查语法的正确性:
```
class Parser {
public:
Parser(const std::string& input) : m_lexer(input), m_currentToken(m_lexer.getNextToken()) {}
bool parse() {
m_root = expr();
return m_currentToken.getType() == Token::EOI;
}
private:
Token consume(Token::TokenType type) {
if (m_currentToken.getType() != type) {
throw std::runtime_error("Parse error!");
}
Token token = m_currentToken;
m_currentToken = m_lexer.getNextToken();
return token;
}
Node* factor() {
Token token = m_currentToken;
if (token.getType() == Token::NUM) {
consume(Token::NUM);
return new Node(token);
} else if (token.getType() == Token::ID) {
consume(Token::ID);
return new Node(token);
} else if (token.getType() == Token::LPAREN) {
consume(Token::LPAREN);
Node* node = expr();
consume(Token::RPAREN);
return node;
} else {
throw std::runtime_error("Parse error!");
}
}
Node* term() {
Node* node = factor();
while (m_currentToken.getType() == Token::TIMES || m_currentToken.getType() == Token::DIVIDE) {
if (m_currentToken.getType() == Token::TIMES) {
Token token = consume(Token::TIMES);
Node* right = factor();
node = new Node(token, node, right);
} else if (m_currentToken.getType() == Token::DIVIDE) {
Token token = consume(Token::DIVIDE);
Node* right = factor();
node = new Node(token, node, right);
}
}
return node;
}
Node* expr() {
Node* node = term();
while (m_currentToken.getType() == Token::PLUS || m_currentToken.getType() == Token::MINUS) {
if (m_currentToken.getType() == Token::PLUS) {
Token token = consume(Token::PLUS);
Node* right = term();
node = new Node(token, node, right);
} else if (m_currentToken.getType() == Token::MINUS) {
Token token = consume(Token::MINUS);
Node* right = term();
node = new Node(token, node, right);
}
}
return node;
}
private:
Lexer m_lexer;
Token m_currentToken;
Node* m_root;
};
```
最后,我们需要定义一个Node类来表示语法树中的节点:
```
class Node {
public:
Node(Token token, Node* left = nullptr, Node* right = nullptr) : m_token(token), m_left(left), m_right(right) {}
Token getToken() const { return m_token; }
Node* getLeft() const { return m_left; }
Node* getRight() const { return m_right; }
private:
Token m_token;
Node* m_left;
Node* m_right;
};
```
现在我们可以使用上述代码来解析算术表达式,并检查其语法:
```
int main() {
std::string input = "x+y*(3*a+7)-b/5";
Parser parser(input);
if (parser.parse()) {
std::cout << "TRUE" << std::endl;
} else {
std::cout << "FALSE" << std::endl;
}
return 0;
}
```
输出结果为TRUE,说明算术表达式的语法是正确的。
阅读全文