Page 1 of 1

มาทำ parser กัน ด้วย bison [แบบสั้นๆ]

PostPosted: Tue Jul 08, 2008 11:50 pm
by natz
เอาแบบสั้นๆเลยนะ ไม่รู้จะได้ใจความรึเปล่านะ

คือเรารู้แล้วใช่ปะว่าทำ scanner (ด้วย flex ) ยังไง แล้ว flex ทำงานยังไง


ขั้นแรกเราต้องรู้ก่อนว่าเราจะทำอะไรถูกปะ เราจะสร้างภาษาให้มี syntax แบบไหน

สมมติเราอยาก ทำภาษาให้ มีการับตัวแปรและตัวเลขเท่านั้น



และตัวแปรเราจะให้ ขึ้นต้นด้วย v และตามด้วยตัวอักษรภาษาอังกฤษตัวพิมพ์ใหญ่เท่านั้น

ภาษานี้มีข้อกำหนดดังนี้
ต้องเป็นตัวแปร แล้วตามด้วยเครื่องหมายเท่ากับ หลังเครื่องหมายเท่ากับก็เป็น expression ก็คือ เป็นตัวเลขหรือตัวแปรก็ได้ บวกหรือลบไปอีกกี่ชุดก็ได้

อย่างเช่น ตามนี้ vA = vB+vC+4+6-vA หรือ vA=3+5; ก็ได้ใช่ปะ


ในส่วนของ scanner
ในการ scan หาตัวแปร
Code: Select all
เราจะเขียนกฎว่า
v[A-Z]         { return VARIABLE; }

return VARIABLE <-- คือตัวคำ ตามกฎแล้วส่งให้ yacc เป็น token ที่ชื่อว่า VARIABLE

[0-9]      { return NUMBER;}
[+-=]         { return *yytext; }

NUMBER ให้รับเลข 0-9 เท่านั้น ตามนี้แปลว่า 11 มันจะตัดเป็น 1 กับ 1 นะ

ถ้าต้องการให้มากกว่าหนึ่งตัว เราก็ต้องเขียนว่า [0-9+]

ไอ้ตรง
return *yytext มันจะ ส่งไปให้ yacc ทั้งหมดเลยที่มันตรงกับ pattern ในนั้นก็มีแค่ + - แล้วก็ = ทีละตัวเท่านั้น
ส่วน
[ \t] ;          /* skip whitespace */

.        yyerror("Unknown character");
ก็ ตามที่ comment บอกเลย


ส่วนใน yacc

เราจะกำหนดตามนี้เลยย

%token NUMBER VARIABLE

จะบอกว่า มันมี token อะไรมั่ง (จาก scanner)

แล้วกฎต่างๆ เราเขียนได้แบบนี้


Code: Select all
%%
program: program     assign     ";"
   |   
   ;
assign:
   VARIABLE '=' expr
   --- ตรงนี้ บอกว่า หน้าเครื่องหมาย = ตัว เป็นตัวแปร (เท่านั้น!) แล้วก็ตามด้วย expression ---
   ;
expr:
   allow   
       |
   expr '+' expr    
       |
   expr '-' expr
   |

   ----ในส่วนนี้บอกว่า  expression จะเป็นตัวเลขตัวเดียว  หรือจะเป็น ตัวแปร ก็ได้ หรือ  จะเป็น (ตัวเลข หรือ ตัวแปร) ตามด้วย (บวก หรือ ลบ)   แล้วตามด้วย (ตัวเลข หรือ ตัวแปร)  ----
   ;
allow:   
   VARIABLE
   |
   NUMBER
       ---- ส่วนนี้บอกว่าจะเป็น ตัวแปรหรือตัวเลขก็ได้ ----
   ;
%%


ปล.ตรง --- คือคำอธิบายคร้าบบบ

PostPosted: Wed Jul 09, 2008 12:01 am
by natz
ไฟล์ เต็มๆเป็นแบบนี้

ไฟล์ small.l


Code: Select all
    /* small.lex #1 */
%{
    #include "y.tab.h"
    #include <stdlib.h>
    void yyerror(char *);
%}

%%

v[A-Z]         { return VARIABLE; }
[0-9]      { return NUMBER;}
[+-=]         { return *yytext; }


[ \t] ;          /* skip whitespace */

.        yyerror("Unknown character");

%%

int yywrap(void)
{
    return 1;
}




ไฟล์ small.y


Code: Select all
%{
    #include <stdio.h>
    int yylex(void);
    void yyerror(char *);
%}

%token NUMBER VARIABLE

%%
program: program assign ";"
   |   
   ;
assign:
   VARIABLE '=' expr
   
   ;
expr:
   allow { printf ("ALLOW\n"); }
   |
   expr '+' expr { printf ("exp + exp\n"); }
   |
   expr '-' expr { printf ("exp - exp\n"); }
   |
   ;
allow:   
   VARIABLE
   |
   NUMBER
   ;
%%

void yyerror(char *s) {
    fprintf(stderr, "%s\n", s);
}
int main(void) {
    yyparse();
    return 0;
}




แล้ว compile ด้วยคำสั่ง

bison -y -d small.y
flex small.l
gcc -c y.tab.c lex.yy.c
gcc y.tab.o lex.yy.o -o small.out
./small.out

PostPosted: Wed Jul 09, 2008 12:07 am
by ClanCy
>> แล้วมันเป็นยังไงหว่าาา



>> HELP ME!!! :!: :!:

PostPosted: Wed Jul 09, 2008 12:12 am
by cruiser
นัทจ๋า ทำให้เค้าหน่อยจิ T-T

PostPosted: Wed Jul 09, 2008 12:21 am
by natz
cruiser wrote:นัทจ๋า ทำให้เค้าหน่อยจิ T-T


imblesipos

PostPosted: Wed Jul 09, 2008 12:27 am
by XEON
:shock: จองไว้ก่อนไว้มาต่อยอด