Skip to content

Commit 47d1b06

Browse files
committed
括弧付きの式に対応
1 parent 6a5f33c commit 47d1b06

File tree

6 files changed

+50
-9
lines changed

6 files changed

+50
-9
lines changed

BNF.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
program = add
22
add = mul ("+" mul | "-" mul)*
3-
mul = num ("*" num | "/" num)*
3+
mul = primary ("*" primary | "/" primary)*
4+
primary = num | "(" add ")"

parser.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <cstdlib>
22
#include <cstring>
3+
#include <iostream>
34
#include <vector>
45
#include "parser.hpp"
56
#include "rook.hpp"
@@ -39,21 +40,33 @@ Node* Parser::add(void)
3940

4041
Node* Parser::mul(void)
4142
{
42-
Node* node = num();
43+
Node* node = primary();
4344

4445
while(1){
4546
if(consume("*")){
46-
node = new Node{ ND_MUL, node, num() };
47+
node = new Node{ ND_MUL, node, primary() };
4748
}
4849
else if(consume("/")){
49-
node = new Node{ ND_DIV, node, num() };
50+
node = new Node{ ND_DIV, node, primary() };
5051
}
5152
else{
5253
return node;
5354
}
5455
}
5556
};
5657

58+
Node* Parser::primary(void)
59+
{
60+
if(consume("(")){
61+
Node* addNode = add();
62+
expect(")");
63+
return addNode;
64+
}
65+
else{
66+
return num();
67+
}
68+
};
69+
5770
bool Parser::consume(const char* str)
5871
{
5972
if(TK_EOF == token->kind) return false;
@@ -66,6 +79,17 @@ bool Parser::consume(const char* str)
6679
return false;
6780
};
6881

82+
void Parser::expect(const char* str)
83+
{
84+
if(TK_EOF == token->kind || strncmp(str, token->str, token->len)){
85+
cerr << "Error : expect \"" << str << "\"" << endl;
86+
exit(1);
87+
}
88+
else{
89+
token++;
90+
}
91+
};
92+
6993
Node* Parser::parse(vector<Token>& tokens)
7094
{
7195
token = tokens.begin();

parser.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ class Parser
1515
Node* num(void);
1616
Node* add(void);
1717
Node* mul(void);
18+
Node* primary(void);
1819

1920
bool consume(const char* str);
21+
void expect(const char* str);
2022

2123
public:
2224
Node* parse(vector<Token>& tokens);

rook.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// トークン関連の定義
99
typedef enum {
1010
TK_NUM, // 数値
11-
TK_OP, // 演算子
11+
TK_RESERVED, // 記号
1212
TK_EOF, // 終端
1313
} TokenKind;
1414

test.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,9 @@ test 8 "2 * 4"
2424
test 3 "12 / 4"
2525
test 10 "5 * 3 - 5"
2626
test 9 "2 + 2 * 5 - 3"
27+
test 1 "(1)"
28+
test 8 "2*(1+3)"
29+
test 5 "1+(2*4)-(2*2)"
30+
test 2 "(2*(1+1)+2)/3"
2731

2832
echo "OK"

tokenizer.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,32 @@ vector<Token> Tokenizer::tokenize(char* input)
1717
input++;
1818
}
1919
else if(strncmp(input, "+", 1) == 0){
20-
Token token = { TK_OP, input, 1 };
20+
Token token = { TK_RESERVED, input, 1 };
2121
tokens.push_back(token);
2222
input++;
2323
}
2424
else if(strncmp(input, "-", 1) == 0){
25-
Token token = { TK_OP, input, 1 };
25+
Token token = { TK_RESERVED, input, 1 };
2626
tokens.push_back(token);
2727
input++;
2828
}
2929
else if(strncmp(input, "*", 1) == 0){
30-
Token token = { TK_OP, input, 1 };
30+
Token token = { TK_RESERVED, input, 1 };
3131
tokens.push_back(token);
3232
input++;
3333
}
3434
else if(strncmp(input, "/", 1) == 0){
35-
Token token = { TK_OP, input, 1 };
35+
Token token = { TK_RESERVED, input, 1 };
36+
tokens.push_back(token);
37+
input++;
38+
}
39+
else if(strncmp(input, "(", 1) == 0){
40+
Token token = { TK_RESERVED, input, 1 };
41+
tokens.push_back(token);
42+
input++;
43+
}
44+
else if(strncmp(input, ")", 1) == 0){
45+
Token token = { TK_RESERVED, input, 1 };
3646
tokens.push_back(token);
3747
input++;
3848
}

0 commit comments

Comments
 (0)