Derleyici Tasarımı
Yüklüyor...
Arıyor...
Eşleşme Yok
bc Grameri

Devasa gramer tanımımız:

struct rdesc_grammar_symbol bc_production_rules
/* <stmt> ::= */ r(
TK(BREAK), TK(SEMI)
alt TK(QUIT), TK(SEMI)
alt TK(RETURN), NT(OPT_EXPR), TK(SEMI)
alt TK(FOR), TK(LPAREN), NT(OPT_EXPR), TK(SEMI),
NT(OPT_EXPR), TK(SEMI),
NT(OPT_EXPR),
TK(RPAREN), NT(STMT)
alt TK(IF), TK(LPAREN), NT(REL_EXPR), TK(RPAREN), NT(STMT)
alt TK(WHILE), TK(LPAREN), NT(REL_EXPR), TK(RPAREN), NT(STMT)
alt TK(PRINT), NT(EXPR), TK(SEMI)
alt TK(LCURLY), NT(STMTS), TK(RCURLY)
alt TK(CST), NT(STMT)
alt NT(EXPR), TK(SEMI)
alt TK(SEMI)
),
/* <stmts> ::= */ r(
NT(STMT), NT(STMTS)
alt EPSILON
),
/* <add-op> ::= */ r(
TK(PLUS)
alt TK(MINUS)
),
/* <mul-op> ::= */ r(
TK(STAR)
alt TK(SLASH)
alt TK(PERCENT)
),
/* <asgn-op> ::= */ r(
TK(PLUSEQ)
alt TK(MINUSEQ)
alt TK(STAREQ)
alt TK(SLASHEQ)
alt TK(PERCENTEQ)
alt TK(CARETEQ)
alt TK(EQ)
),
/* <rel-op> ::= */ r(
TK(LT)
alt TK(GT)
alt TK(EQEQ)
alt TK(EXCLEQ)
alt TK(LTEQ)
alt TK(GTEQ)
),
/* <unary-op> ::= */ r(
TK(PLUS)
alt TK(MINUS)
alt EPSILON
),
/* <incr-decr-op> ::= */ r(
TK(PLUSPLUS)
alt TK(MINUSMINUS)
),
/* <opt-incr-decr-op> ::= */ r(
TK(PLUSPLUS)
alt TK(MINUSMINUS)
alt EPSILON
),
/* <add-expr> ::= */
rrr(ADD_EXPR, (NT(MUL_EXPR)), (NT(ADD_OP), NT(MUL_EXPR))),
/* <mul-expr> ::= */
rrr(MUL_EXPR, (NT(EXP_EXPR)), (NT(MUL_OP), NT(EXP_EXPR))),
/* <exp-expr> ::= */
rrr(EXP_EXPR, (NT(FACTOR)), (TK(CARET), NT(FACTOR))),
/* <factor> ::= */ r(
NT(UNARY_OP), NT(ATOM)
),
/* <atom> ::= */ r(
NT(INCR_DECR_OP), TK(IDENT)
alt TK(IDENT), NT(OPT_INCR_DECR_OP)
alt TK(LPAREN), NT(EXPR), TK(RPAREN)
alt TK(INT)
alt TK(FLOAT)
),
/* <asgn-expr> ::= */ r(
TK(IDENT), NT(ASGN_OP), NT(ADD_EXPR)
),
/* <rel-expr> ::= */ r(
NT(ADD_EXPR), NT(REL_EXPR_OPT_REL)
),
/* <rel-expr-opt-rel> ::= */
ropt(NT(REL_OP), NT(ADD_EXPR)),
/* <opt-expr> ::= */
ropt(NT(EXPR)),
/* <expr> */ r(
NT(ASGN_EXPR)
alt NT(REL_EXPR)
)
};
struct rdesc_grammar_symbol bc_production_rules[BC_NT_COUNT][BC_MAX_ALT_COUNT+1][BC_MAX_ALT_SIZE+1]
[Token/nonterminal ID]
#define BC_MAX_ALT_COUNT
Definition bc-grammar.h:18
#define BC_NT_COUNT
[Gramer declaration]
Definition bc-grammar.h:16
#define BC_MAX_ALT_SIZE
Definition bc-grammar.h:20

Burada kullandığımız token ve nonterminal ID'lerinin enum'u ise:

enum bc_tk_id {
TK_PLUS, TK_MINUS, TK_STAR, TK_SLASH, TK_PERCENT, TK_CARET,
TK_PLUSEQ, TK_MINUSEQ, TK_STAREQ, TK_SLASHEQ, TK_PERCENTEQ, TK_CARETEQ, TK_EQ,
TK_PLUSPLUS, TK_MINUSMINUS,
TK_LT, TK_GT, TK_EQEQ, TK_EXCLEQ, TK_LTEQ, TK_GTEQ,
TK_LPAREN, TK_RPAREN, TK_LCURLY, TK_RCURLY, TK_SEMI, TK_COMMA,
TK_DEFINE, TK_BREAK, TK_QUIT, TK_PRINT,
TK_RETURN, TK_FOR, TK_IF, TK_WHILE, TK_CST,
/* TK_IDENT, TK_INT ve TK_FLOAT tokenizer tarafından tanımlanır */
};
enum bc_nt_id {
NT_STMT, NT_STMTS,
NT_ADD_OP, NT_MUL_OP,
NT_ASGN_OP, NT_REL_OP,
NT_UNARY_OP, NT_INCR_DECR_OP, NT_OPT_INCR_DECR_OP,
NT_ADD_EXPR, NT_ADD_EXPR_REST,
NT_MUL_EXPR, NT_MUL_EXPR_REST,
NT_EXP_EXPR, NT_EXP_EXPR_REST,
NT_FACTOR, NT_ATOM,
NT_ASGN_EXPR, NT_REL_EXPR, NT_REL_EXPR_OPT_REL,
NT_OPT_EXPR,
NT_EXPR,
};
/* Bu string karşılıkları tokenizer'a punctuation ve keyword eklemek için
* kullanacağız. */
const char *bc_tk_names[] = {
"+", "-", "*", "/", "%", "^",
"+=", "-=", "*=", "/=", "%=", "^=", "=",
"++", "--",
"<", ">", "==", "!=", "<=", ">=",
"(", ")", "{", "}", ";", ",",
"define", "break", "quit", "print",
"return", "for", "if", "while", "cst",
/* librdesc'in dump_bnf fonksiyonuyla gramer yapımızı birazdan print
* edeceğiz. */
[TK_INT] = "@int", [TK_FLOAT] = "@float", [TK_IDENT] = "@ident",
};
/* Nonterminal isimleri ve yukarıdaki [] içindeki token isimleri, dump_bnf
* özelligi için. */
const char *bc_nt_names[] = {
"stmt", "stmts",
"add_op", "mul_op",
"asgn_op", "rel_op",
"unary_op", "incr_decr_op", "opt_incr_decr_op",
"add_expr", "add_expr_rest",
"mul_expr", "mul_expr_rest",
"exp_expr", "exp_expr_rest",
"factor", "atom",
"asgn_expr", "rel_expr", "rel_expr_opt_rel",
"opt_expr",
"expr",
};
const char * bc_tk_names[]
Definition bc-grammar.h:56
bc_nt_id
Nonterminal ID.
Definition bc-grammar.h:36
bc_tk_id
Token ID.
Definition bc-grammar.h:24
const char * bc_nt_names[]
Definition bc-grammar.h:73
#define TK_IDENT
Identifier token ID'si.
Definition tokenizer.h:28
#define TK_INT
Tam sayı token ID'si.
Definition tokenizer.h:22
#define TK_FLOAT
Ondalık sayı token ID'si.
Definition tokenizer.h:25

ID ve string'ler üzerinden tokenizer üretmek için:

{
for (int i = TK_PLUS; i <= TK_COMMA; i++)
for (int i = TK_DEFINE; i <= TK_CST; i++)
}
void bc_tokenizer_init(struct tokenizer *tokenizer)
[Gramer declaration]
tokenizer.
Definition tokenizer.h:33
void tokenizer_add_keyword(struct tokenizer *tokenizer, const char *keyword, size_t id)
Tokenizera bir keyword kaydeder.
void tokenizer_add_punctuation(struct tokenizer *tokenizer, const char *punctuation, size_t id)
Tokenizera bir punctuation kaydeder..
void tokenizer_init(struct tokenizer *tokenizer)
[Token tanımı]

Aşağıdaki fonksiyon, grameri daha kolay okunur bir formatta ekrana yazdırır:

rdesc_dump_bnf(stdout, &grammar, bc_tk_names, bc_nt_names);

Devasa grameri oluşturduğu ağacı traverse ederken daha net anlayacağız: bc Interpreter.