*, /, ()を言語に追加するには演算子の優位順位を決めなければならない
– パーサの実装
入力はフラットなトークンの列で出力は入れ子構造を表す木にする
単純な生成規則
expr = num(“+” num | “-” num)*
mul = num(“*” num | “/” num)*
具象構文木(concrete syntax tree)
再帰を含む生成規則
expr = mul(“+” mul | “-” mul)*
mul = primary(“*” primary | “/” primary)
primary = num | “(” epr “)”
再帰下降構文解析
expr = mul(“+” mul | “-” mul)*
mul = primary(“*” primary | “/” primary)*
primary = num | “(” epr “)”
typedef enum {
ND_ADD,
ND_SUB,
ND_MUL,
ND_DIV
ND_NUM,
} NodeKind;
typedef struct Node Node;
struct Node {
NodeKind kind;
Node *lhs;
Node *rhs;
int val;
};
Node *new_node(NodeKind kind, Node *lhs, Node *rhs){
Node *node = calloc(1, sizeof(Node));
node->kind = kind;
node->lhs = lhs;
node->rhs = rhs;
return node;
}
Node *new_node_num(int val) {
Node *node = calloc(1, sizeof(Node));
node->kind = ND_NUM;
node->val = val;
return node;
}
Node *expr(){
Node *node = mul();
for(;;){
if(consume('+'))
node = new_node(ND_ADD, node, mul());
else if(consume('-'))
node = new_node(ND_SUB, node, mul());
else
return node;
}
}
Node *mul(){
Node *node = primary();
for(;;){
if(consume('*'))
node = new_node(ND_MUL, node, mul());
else if(consume('/'))
node = new_node(ND_DIV, node, mul());
else
return node;
}
}
Node *primary(){
if(consume('(')){
Node *node = expr();
expect(')');
return node;
}
return new_node_num(expect_number());
}