วันอาทิตย์, มิถุนายน 27, 2547

นั่งอ่านวิธีเขียน grammar ของ yacc ได้พักใหญ่แล้ว...เริ่มเห็นลู่ทาง...ค่อยยังดีหน่อย..

==> Parsing a configuration file

สมมติจะ parse configuration ตัวนี้

zone "." {
type hint;
file "/etc/bind/db.root";
};

เริ่มต้นก็ต้องเขียน lex file ขึ้นมาก่อน return ให้ yacc เข้าพระทัยซะด้วย

%{
#include
#include "y.tab.h"
%}

%%

zone return ZONETOK;
file return FILETOK;
[a-zA-Z][a-zA-Z0-9]* yylval=strdup(yytext); return WORD;
[a-zA-Z0-9\/.-]+ yylval=strdup(yytext); return FILENAME;
\" return QUOTE;
\{ return OBRACE;
\} return EBRACE;
; return SEMICOLON;
\n /* ignore EOL */;
[ \t]+ /* ignore whitespace */;
%%

สังเกตว่า yylval จะไม่ใช่ integer แต่เป็น char * ดังนั้นก็เลยต้อง #define YYSTYPE char * ให้ yacc รู้จักก่อน

ตอนเริ่มเขียน yacc grammer นี้ชักจะเริ่มมั่วนิดส์นึง

เริ่มการ recusive ที่ root

commands:
|
commands command SEMICOLON
;

คือว่าแต่ละ command แยกกันด้วย ";"(semicolon)

command:
zone_set
;

zone_set:
ZONETOK quotedname zonecontent
{
printf("Complete zone for '%s' found\n",$2);
}
;
มี zonecontent ด้วย

zonecontent:
OBRACE zonestatements EBRACE

จะต้องมี { OBRACE และ } EBRACE

quotedname:
QUOTE FILENAME QUOTE
{
$$=$2;
}
นั่นคือ quotedname เท่ากับ filename

NOTE: this grammar chokes on filenames without either a '.' or a '/' in them.

zonestatements:
|
zonestatements zonestatement SEMICOLON
;

zonestatement:
statements
|
FILETOK quotedname
{
printf("A zonefile name '%s' was encountered\n", $2);
}
;

This is a generic statement that catches all kinds of statements within the 'zone' block. We again see the recursiveness.

block:
OBRACE zonestatements EBRACE SEMICOLON
;

statements:
| statements statement
;

statement: WORD | block | quotedname


ไม่มีความคิดเห็น: