ดาวน์โหลดงานนำเสนอ
งานนำเสนอกำลังจะดาวน์โหลด โปรดรอ
1
Lex & Yacc โดย...นายชัชวาลย์ ฮาสุวรรณกิจ
2
UNIX ได้จัดเครื่องมือสำหรับการพัฒนาตัวภาษา
(Language Development Tools) เครื่องมือนี้คือ lex ( LEXical analyzer) yacc (Yet Another Compiler Compiler)
3
Lex เป็นเครื่องมือที่ใช้เพื่อตรวจจับรูปแบบเหมือน (Pattern matching) จาก Input ที่อ่านเข้ามาทีละอักขระ ได้เป็น Tokens ต่างๆ ผลลัพธ์ที่ได้จาก lex เป็นชุดคำสั่งย่อยภาษาซี ชื่อ yylex() มักเรียกอีกอย่างว่า Scanner Yacc เป็นเครื่องมือที่ใช้วิเคราะห์วากยสัมพันธ์ (Syntax Analysis) ผลลัพธ์ที่ได้จาก yacc เป็นชุดคำสั่งย่อยภาษาซี ชื่อ yyparse() มักเรียกอีกอย่างว่า Parser
6
Lex มี Input เป็น Lex specifications file
และมี Output ออกเป็นภาษา C Lex Specifications file มีรูปแบบทั่วไปดังนี้ definitions %% lex regular expressions and actions User functions
7
Lex specifications file
ตัวอย่าง 1 %% [0-9]+ { printf(“INTEGER\n”); } [-*/+] { printf(“OPERATOR\n”); } ตัวอย่าง 2 %% [0-9]+ { return (INT); } [-*/+] { return (OPR); }
8
Lex Definitions INTEGER [0-9]+ %% { INTEGER } printf(" Integer encountered\n"); { INTEGER } \. { INTEGER } { printf(" Real number encountered\n"); }
9
Yacc specifications file
มีโครงสร้างที่คล้ายคลึงกับ Lex specifications file ดังนี้ declarations %% yacc rules and actions User functions
10
ตัวอย่าง Yacc specifications program
สำหรับ Parser อย่างง่ายข้างต้นเขียนได้ดังนี้
11
%token INT OPR %start expr %% expt : INT OPR INT { printf("The input expression was syntactically correct\n"); } | error printf("The input expression was syntactically incorrect\n");
12
Main program #include <stdio.h> main( ) { yyparse( ); } #include "y.tab.c" #include "lex.yy.c"
13
การ Run Parser lex file-name File-name เป็นชื่อของ File ที่มี Lex specifications ในการ Execute คำสั่งจะสร้าง File ที่เรียกว่า lex.yy.c ซึ่งเป็น C program ที่มี function yylex อยู่ yacc file-name File-name เป็นชื่อของ File ที่มี yacc specifications ในการ Execute คำสั่งจะสร้าง File ที่เรียกว่า y.tab.c ซึ่งเป็น C program ที่มี function yyparse
14
สร้าง a.out parser ด้วยการใช้คำสั่งดังข้างล่างนี้ cc main.c -ly
การ Run Parser สร้าง a.out parser ด้วยการใช้คำสั่งดังข้างล่างนี้ cc main.c -ly การ Compile จะใช้ Standard CC command และ เราสามารถเรียกใช้ Yacc library ได้โดยการใช้ -ly option เราสามารถเรียกใช้Lex library โดยการใช้ -ll option ในคำสั่ง CC command line แต่ไม่จำเป็นเสมอไปทุกครั้งที่จะต้องใช้ Yacc และ Lex libraries -ly ใช้ Yacc library เพราะว่ามีการใช้ Error option
18
Context Sensitivity Lex ได้มีกลไกที่เป็นเงื่อนไขในการทำงาน (Start condition) สำหรับ กรณี Left context sensitivity ไว้ให้ Left context sensitivity บอกว่า ความหมายของ Token หนึ่งจะขึ้นอยู่กับ Token ที่อยู่ก่อนหน้ามัน หลักการของการใช้ start condition คือเพื่อ Set และ Unset ตัว Token นั้น เมื่อมีเหตุการณ์เกิดขึ้น Start conditions ใน Lex กำหนดได้ตามรูปแบบนี้ %start start1 start2 start3 …
19
โดยที่ start1, start2 และ start3 เป็นชื่อของ Start conditions
การ Set start condition ใช้ Statement ดังนี้ BIGIN start1 โดยที่ start1 เป็นชื่อของ Start condition การ Unset start condition ต่างๆ ใช้ Statement ดังนี้ BEGIN 0; การ Match สตริงหนึ่งกับ Regular expression ที่มี Start condition เขียนได้ดังนี้ < start1 > reg_expr { actions }
20
ตัวอย่างการใช้ Start Condition
แปลงตัวเลขจำนวนนับสองหลักไปเป็นการแสดงด้วยตัวหนังสือ โดยให้ input ขึ้นต้นด้วย $ (Dollar sign) แล้วตามหลังด้วยตัวเลขสองตัว ตัวอย่างเช่นถ้า Input เป็น $23 จะได้ output เป็น Twenty three dollars เราสามารถเขียน Lex specifications file สำหรับโปรแกรมนี้ดังดังนี้
21
%start TT ZZ DD TN %% \ $ { BEGIN TT; } < TT > [ 0-9 ] { tenth = yytext[0]; BEGIN 0; Switch (yytext[0]) { case '0' : BEGIN ZZ; break; case '1' : BEGIN TN; break; default : BEGIN DD; break; }
22
< ZZ > [ 0-9 ] { BEGIN 0;
Switch (yytext[0]) { case '0' : printf("Zero dollars"); break; case '1' : printf("One dollars"); break; case '2' : printf("Two dollars"); break; case '3' : printf("Three dollars"); break; case '4' : printf("Four dollars"); break; case '5' : printf("Five dollars"); break; case '6' : printf("Six dollars"); break; case '7' : printf("Seven dollars"); break; case '8' : printf("Eight dollars"); break; case '9' : printf("Nine dollars"); break; }
23
< TN > [ 0-9] { BEGIN 0;
Switch (yytext[0]) { case '0' : printf("Ten dollars"); break; case '1' : printf("Eleven dollars"); break; case '2' : printf("Twelve dollars"); break; case '3' : printf("Thirteen dollars"); break; case '4' : printf("Fourteen dollars"); break; case '5' : printf("Fifteen dollars"); break; case '6' : printf("Sixteen dollars"); break; case '7' : printf("Seventeen dollars"); break; case '8' : printf("Eighteen dollars"); break; case '9' : printf("Nineteen dollars"); break; }
24
< DD > [ 0-9 ] { BEGIN 0; Switch (tenth) { case '2' : printf("Twenty "); break; case '3' : printf("Thirty "); break; case '4' : printf("Forty "); break; case '5' : printf("Fifty "); break; case '6' : printf("Sixty "); break; case '7' : printf("Seventy "); break; case '8' : printf("Eighty "); break; case '9' : printf("Ninety "); break; }
25
case '0' : printf("dollars"); break;
Switch (yytext[0]) { case '0' : printf("dollars"); break; case '1' : printf("One dollars"); break; case '2' : printf("Two dollars"); break; case '3' : printf("Three dollars"); break; case '4' : printf("Four dollars"); break; case '5' : printf("Five dollars"); break; case '6' : printf("Six dollars"); break; case '7' : printf("Seven dollars"); break; case '8' : printf("Eight dollars"); break; case '9' : printf("Nine dollars"); break; }
26
main function โปรแกรมภาษา C เขียนได้ดังข้างล่างนี้
#include < stdio.h> char tenth; main( ) { while (1) yylex( ); } yywrap( ) exit (0); #include " lex.yy.c "
27
Predefined Pseudovariables
ค่าที่ส่งกลับมาสำหรับแต่ละ Token โดย Lexical analyzer สามารถจะเข้าถึงและนำไปใช้งานได้ภายในกฎของ Yacc Precefined pseudovariables ถูกใช้ในการเข้าถึงค่าต่างๆของ Token ใช้สัญลักษณ์เริ่มต้นด้วย $ (Dollar Sign) แล้วตามด้วยตัวเลข (Integer) โดยที่เลข Integer นี้จะอ้างถึงตำแหน่งของ Terminal symbol ภายใน Rule และ $$ จะอ้างอิงถึง Left-hand nontermal symbol ในกฎดังนี้ result : VAR1 '+' VAR2 '+' VAR3 { $$ = $1 + $3+ $5; };
28
$1 ถูกกำหนดค่าให้โดย VAR1,
$2 จะถูกกำหนดค่าให้โดย Terminal symbol +, และต่อไปตามลำดับ...จนถึง $5 จะถูกกำหนดค่าโดย VAR3 โดยผลของการคำนวณจะส่งไปให้กับ Nonterminal result Predefined pseudovariables จะมีประโยชน์โดยเฉพาะ ใช้ในการวิเคราะห์การกระจาย (Parsing) และ การหาค่าจากรูปประโยคทางคณิตศาสตร์ (Arithmetic expressions)
29
มาทำโปรแกรม Calculator กันเถอะ
30
Lex specifications file
> cat cal.l %{ #include "y.tab.h" extern char yytext[]; extern int yylval; %} %% [0-9]+ { yylval = atoi(yytext); return INTEGER; } (ต่อ)
31
(ต่อ) [- +\n] return *yytext; [\t] ; { exit(0); } %% yywrap() { return 1; }
32
Yacc specifications file
> cat cal.y | more %token INTEGER %% program:program expr '\n' {printf("%d\n",$2);} | ; expr: INTEGER {$$ = $1;} |expr '+' expr {$$ = $1 + $3 ;} |expr '-' expr {$$ = $1 - $3 ;} ; (ต่อ)
33
(ต่อ) %% yyerror() { exit(0); } main(){ yyparse(); return 0;
34
Compile และRun โปรแกรม
>yacc –d cal.y > lex cal.l > cc lex.yy.c y.tab.c -o cal > ./cal 3-1 /* input */ 2 /* ผลลัพธ์ */ 4-2+1 1 /* ผลลัพธ์ */ 9 /* ผลลัพธ์ */ . /* exit */ >
35
REFERENCE UNIX UTILITIES, International Edition, R.S. Tare, McGraw-Hill, 1988 “A Compact Guide to LEX and YACC” Access date Feb,4 2001
งานนำเสนอที่คล้ายกัน
© 2024 SlidePlayer.in.th Inc.
All rights reserved.