Lex & Yacc(Ұ  ߽)

 ...    Ʈ  ִ ۼ߾
Դϴ. ^^;  ؽƮ   ֵ ٲپ Խմϴ. 
lex & yacc .  :)

ۼ :   byosmosis@yahoo.com
Խ : 97 11 1


0.   (Lex & Yacc)
  Lex Yacc Է± ˻ м ϰ ϱ Ͽ ߵǾ.
Է¿     ϴ  α׷    
Ȯϰ ׸ ణ    Ǵ  lex yacc
Ư¡̴.  
    Lex Yacc ̴ δ ڿ ڸ  ϴ ,
Ϸ    ˻,  м  ̳, Ÿ
̽ SQL  üũϴ ,  lex ̿  м 
 쿡 ̿ȴ.
 
뼭 lex yacc  Ұ lex yacc ̿ϴ  ׸
ణ lex yacc   ؼ Ұϰ Ѵ.


   .

1. Lex & Yacc
1.1 Lex (Lex ̿  α׷)
1.2 Lex Yacc (Lex scanner, Yacc parser)
1.3 Yacc 
1.4 Lex Yacc 
1.5 Makefile ̿
3. 

1. Lex & Yacc
lex yacc (Bell Laboratories) 70뿡 ߵǾ, Ŀ
̰͵ н ǥ ƿƼ  Ǿ System V ʱ BSD 
 AT&T  ̿ǰ  ο BSDδ flex Berkely
yacc  ̿ǰ ִ.
 FSF(Free Software Foundation) GNU Ʈ bison̶ Ҹ 
yacc      BSD GNU Ʈ flex(Fast
Lexical Analyzer Generator)ܿ  üϿ   ٸ
̸ lex yacc  ǰ ִ.

 MS-DOS OS/2  OS󿡼 ̿  ִ lex yacc 
    MKS(Mortice Kern Systems Inc.) ִ.


1.1 Lex (Lex ̿  α׷)

)  Lex Ʒ  %% %%̿ lex ǰ  Ŀ
       C ȴ.
%%
.|\n    ECHO;
%%
 
main()
{
        yylex();
}
 
 ǥԷ ǥ    lex α׷ 
ǥ . \n ǥõǴ ڰ   ״ ش.  (
lex   default̴.) 

 ٸ    
 [\t ]+          ;       # whitespace Ѵ
 %% %%̿ ԽŰ ̶簡 ϳ ̻  ִ  C
 ƹ ó ִ ';' Ͽ  ƹ ó 
ʴ´.(ȭ鿡  ޽   ʴ´.)
 
 ҽ simple.l̶ ϸ( ǥô  Է)
[ post ] % lex simple.l
                           # lex C, lex.yy.c 
[ post ] % cc lex.yy.c -o simple -ll
                           # lex̺귯  
[ post ] % ./simple < simple.l
                           # simple.l ǥԷ ϴ α׷ 
%%
.|\n ECHO;
%%

main()
{
        yylex();
}

  Ǿ UNIX cat   α׷ ϼȴ.(ڰ 
cat     α׷ )

 lex    definitions, rules, user code section
   ̷.

definitions 
  # rules pattern ϰ ϱ   ʱ 
  # Cڵ Խ %{, }% ȣ ǥϰ ̿   
%%
rules  
  # pattern action ̷
  # Cڵ {, } μ ǥ
%%
user code 
  # yylex()Լ ڰ ϴ C ƾ ̷


)

 %% %%̿ lex ϱ  C ϱ⸦ ҽÿ
 %{ %} C ̶ ǥø ϰ  ̿   ִ.
 
%{
        /*
         * My favorite...
         */
%}
%%

[\t ]+  ;
rain |
rose            { printf("%s!! That is my favorite.\n", yytext); }
love |
story           { printf("%s!! I like a love story. ^_~\n", yytext); }
"potato chip" |
potato |
chip  { printf("%s...!! now and then, I have a potato chip.\n", yytext); }
 
[A-Za-z]+ { printf("%s..., what is that?\n", yytext); }
 
.|\n    { ECHO; }
 
%%

main()
{
        yylex();
}

yytext lex Ǵ Է ؽƮ  global character pointer̴.
 ҽ simple.l   Ͽ  

[ post ] % ./favor
potato chip
potato chip...!! now and then, I have a potato chip.
 
love7
love!! I like a love story. ^_~
7
distress
distress...,  what is that?
  ȴ.

lovestory
lovestory...,  what is that?

love story
love!! I like a love story. ^_~
story!! I like a love story. ^_~

 Ÿ  °  óϱ⸦ ϴ Ͽ ؼ ó
̷.  love7 쿡 love  ó ְ 7 ĺ ƴϹǷ
ٿ ڰ ȴ.
  ٷ  'love story' love νϰ whitespace ĭ 
νϰ
 story ν ̴.   love  ó ĭ  ƹ
ó story  ó    ̴.
 μ loveyou Է ߴٸ love  you    ƴ϶
ϳ   distress       ִ.


)       ٸ ڿ  C 
enum
      Ͽ ɺ ̺  ̿ϴ  ش.

[ post ] % cat number.l
%{
enum {
        NONE = 0,
        ONE,
        TWO,
        THREE,
        FOUR,
        FIVE,
        SIX,
 SEVEN
};

int number;
void action();
%}

%%
oneone  { number = SEVEN; action(); }
one |
ONE  { number = ONE; action(); }
two |
TWO  { number = TWO; action(); }
three |
THREE  { number = THREE; action(); }
four |
FOUR  { number = FOUR; action(); }
five |
FIVE  { number = FIVE; action(); }
six |
SIX  { number = SIX;  action(); }
[a-zA-Z]+ { number = NONE; action(); }
%%

void action()
{
        if (number != NONE)
                printf("%s is %d\n", yytext, number);
        else
                printf("%s?? I don't learn it.\n", yytext);
}
 
main()
{
        yylex();
}

[ post ] % ./number
tow
tow?? I don't learn it.
 
five
five is 5
 
four7
four is 4
7
SIX
SIX is 6
 
ten
ten?? I don't learn it.

oneone
oneone is 7

twotwo
twotwo?? I don't learn it.

two two
two is 2
 two is 2

  'two two' two  ó ְ ' ' ĭ  ٿ
ܼ ְ ٷ Ѿ ʰ  two óǾ Ÿ
̴.   ° two տ ĭ ϳ  ִ.
׸ oneone̶    one  ƴ oneone 
   ڿ 켱  ̴.( ǥ )


)  lex   ͺ ణ  ڿ ڿ 
      νϴ μ ݸ Ű   α׷  
      ִ.    ܼ , ,  Ǵ μ
        Ͽ Ÿ ϴ ̴.

%{
/* need this for the call to atof() below */
#include <math.h>
%}

DIGIT    [0-9]  /* ũθ Ѵ */
ID       [a-z][a-z0-9]*

%%
{DIGIT}+  { printf( "An integer: %s (%d)\n", yytext, atoi( yytext ) ); }
{DIGIT}+"."{DIGIT}* { printf( "A float: %s (%g)\n", yytext, atof( yytext ) ); 
}
if|then|begin|end|procedure|function { printf( "A keyword: %s\n", yytext ); }
{ID}   { printf( "An identifier: %s\n", yytext ); }
"+"|"-"|"*"|"/"  { printf( "An operator: %s\n", yytext ); }
"{"[^}\n]*"}"  ; /* { }   ּ Ѵ. */
[ \t\n]+  ; /* whitespace Ѵ. */
.   printf( "Unrecognized character: %s\n", yytext );
%%

main( argc, argv )
int argc;
char **argv;
{
    ++argv, --argc;  /* skip over program name */
    if ( argc > 0 )
            yyin = fopen( argv[0], "r" );
    else
            yyin = stdin;

    yylex();
}

  yyin   Է Ŀǵ λ ùڰ Ű
  ó  ȭ鿡 ǥԷ ޾ ó  
ó   ְ Ѵ.



1.2 Lex Yacc (Lex scanner, Yacc parser)

Lex scanner Yacc parser  ϴ 찡 κε, Yacc Lex
 ȴ.  Lex Է¹ڿ   ˻ ϰ 
м Yacc ϴ ̴.  Yacc Է¿  ū(token) ʿϸ, 
Lex ϴ yylex()Լ ȣϿ, Էµ  ū 迭 ־
 ´ üũϸ鼭  ǿ ´  ϰ ȴ.
ٸ ǥϸ, Lex Yacc  ÿ  ÿ yacc 
main()Լ yyparse()Լ yacc   м⸦ θ,
yyparse()Լ yylex() lex  ִ ؼ(lexer) ̿ؼ
Է¿ ó ū ̾ƿ ȴ. 
  lex '[\t ]+' ǥõǾ ̳ ǰ  whitespaceڴ
κ α׷  óϱ⸦ ġ ʴ´.     ǹ
 ڳ ó ʿ䰡  ڿ ؼ   parser Ѱ
ʿ䰡 . ׸   ó ڰ    (ū) yacc
parser ѱ  ó  ̴.  ̷ 찡 lex yacc  
Ǵ      ̴.


 MS-DOS OS/2  OS󿡼 ̿  ִ lex yacc ߴ
   MKS(Mortice Kern Systems Inc.) WWW Ͽ Netscape Fasttrack̳
   Microsoft IIS  ˻   ̿  ְԵ Ͽ.


1.3 Yacc 

  Yacc Yet Another Compiler Compiler ڷ, Ϸ  
α׷ compiler-generator Ǵ compiler-compiler θµ, 
Yacc BNF   rules ׸κ parser 
α׷̴.(Yacc Է BNF ϰ   ̴.)
  Yacc ̿ α׷ portable C Ϸ, APL, Pascal, Ratfor,
tbl, eqn  ִ.

 Yacc ̸, Yacc Lex    ִµ δ
Lex Yacc    ̴.

definitions 
   # Cڵ Խ %{, }% ȣ ǥϰ ̿   
%%
rules 
   #  rule "LHS: RHS;"   ̷
%%
user code
   # lex ս yylex() ̿Ѵ.

 LHS left-hand symbol ڷ ':' ʿ  statement,
   expression  ʿ  ȣ ϸ,  RHS right-hand
   symbol ڷ ':' ʿ  ȣ Ѵ.
    rule  ';' ǥѴ.

) yacc ظ        
        ⸦ ٰ   װ    ̸
       Ʒ .

[ post ] % cat y_calc.y
%token NAME NUMBER
%%
statement:    NAME '=' expression
            | expression  { printf("= %d\n", $1); }
            ;
expression:   expression '+' NUMBER { $$ = $1 + $3; }
            |   expression '-' NUMBER { $$ = $1 - $3; }
            |   NUMBER  { $$ = $1; }
            ;
[ post ] % cat y_calc.l
%{
#include  "y.tab.h"
extern int  yylval;
%}
%%
[0-9]+ { yylval = atoi(yytext); return NUMBER;  }
[\t ]+ ;
\n return 0;    /*  Էó  */
. return  yytext[0];
%%

yacc lex ȣϸ(=yylex() ȣϸ) NAME, NUMBER, ׸ +, -, =
· ū Ѱ ޴´.(Խ ǥ ؼ ' 'ȿ  ڴ 
  ü )
 y_calc.y , $1, $2, $3  Է¹ ū ġ شϴ 
 ְ,   yacc yylval type int,  ó Ǿ %d
 Ѵ.(y_calc.l ϰ ִ yylval̶  union
Ǿ ִ.  ̰ lex ܺκ  ̿Ͽ yyparse()Լ
ȣϴ yacc óϵ  ϰ Ǵ ) ׸ $2 쿡
شϴ  ڿ شϴ ڰ   expression RHS
{ } ȿ +,  - ̿ϰ ִ.  ׸ $$ LHS , expression
 ȴ.

yacc  ϱ ؼ example.y yacc ۼǸ yacc 
̿Ͽ, yyparse() м Լ  y.tab.c C ȭ 
 ؼ 'yacc example.y' ϰ CϷ ̿ؼ, y.tab.o 
Ʈ ȭ  Ŀ, ڵ⳪ ٸ α׷ ũϿ ϴ 
 .
 α׷(y_calc.y y_calc.l) Ͽ   Ʒ . 
[ post ] % yacc -d y_calc.y /* y.tab.h y.tab.c  */
[ post ] % lex y_calc.l
[ post ] % cc -o y_calc y.tab.c lex.yy.c -ly -ll
[ post ] % ./y_calc
1+101
= 102
[ post ] % ./y_calc
1000-300+200+100
= 1000

⼭ y.tab.h lexer includeϱ , yacc ֱ 
-d ġ ̿Ͽ. lex ̿Ͽ, lex.yy.c , yacc ̿Ͽ,
y.tab.c  liby.a libl.a ũϿ ϴ ȭ  ȴ.

 Yacc ȣ  -    غ.
    expression : expression '+' expression
        |        expression '-' expression
        |        expression '*' expression
        |        expression '/' expression
        |        '-' expression
        |        '(' expression ')'
        |        NUMBER
   yacc  , 2+3*4 ĽϷ ϸ, ׸ , (2+3)*4
ĽƮ   ְ, 2+(3*4) ó  ְ Ǿ,  
ȴ.  2-3-4-5 쿡, 2-(3-(4-5)), (2-3)-(4-5) 
 ȴ
   ָ   ٲ  ִµ, 켱 չĢ
 ϴ  Ѱ    ʰ  ̰,
ٸ Ѱ ̷  ذϱ Ͽ yacc Ǿ ִ ϴ
 ̿Ͽ(%prec, %left, %right, ...) 켱 չĢ ϴ
̴.
  ̸ ذϴ   ٲٴ  ⺻ ̵ 켱
  ڿ ؼ LHS  , ̸ reduceǵ ϴ
̸, չĢ ؼ   ذ  ִ.  
ٲپ shift/reduce conflict ذ  Ʒ .
expression: expression '+' mulexp
  |   expression '-' mulexp
  |   mulexp
  ;
mulexp : mulexp '*' primary
  |   mulexp '/' primary
  |   primary
  ;
primary:  '(' expression ')'
  |   '-' primary
  |   NUMBER
  ;
 ذϴ Ǵٸ  yacc ϴ ɾ ̿ϴ 
 ɾ ̿ؼ, 켱  չĢ   ְ ȴ. 
     .

%left  '+' '-'
%left  '*' '/'
%right '='
%nonassoc  UMINUS /* unary operator Ƿ չĢ  ȵȴ.  */

  ϰ Ǹ, + - * / =  켱 + -   , * /
װͺ , Կ =  , ȣ -   켱
ٴ  ְ ִ.   + -, *, /  չĢ ,
Կ =  չĢ .

%token NAME NUMBER
%left '-' '+'
%left '*' '/'
%nonassoc UMINUS
expression:     expression '+' expression
         |      expression '-' expression
         |      expression '*' expression
         |      expression '/' expression
         |      '-' expression %prec UMINUS
         |      '(' expression ')'
         |      NUMBER
         ;
 ߰ ̴ %prec UMINUS '-' expression  ڿ Ľϰ
Ǹ - ؼ UMINUS  켱 ϶ ǹ̴.  
, ȣ  ̴ shift/reduce conflict 涧, 켱 
չĢ ν,  ذ  ְ ȴ.

 Ǵٸ Yacc ȣ, LALR(1) ƴ  
   캸.

phrase: cart_animal AND CART
        | work_animal  AND PLOW
cart_animal: HORSE | GOAT
work_animal: HORSE | OX

  , HORSE AND CART  Է  쿡, HORSE
cart_animal reduceؾ ϴ, work_animal reduceؾ ϴ ˷,
HORSE , AND , CART     ְ ȴ.
Yacc ó    , yacc  м ϴµ ϴ 
LALR(1)ε LALR LookAhead Left Recursive, ,   ܾ  
´    ִٴ ̱ ̴.  , HORSE  2
ܾ  о ϴ ε,   LALR(2)̸, yacc  
lookahead   ִ  LALR(1) شϹǷ,   ó
 .      LALR(1) ٲپ ־ Ѵ.

phrase -> cart_animal  CART
         | work_animal  PLOW
cart_animal  -> HORSE | GOAT
work_animal -> HORSE | OX

   HORSE , ٷ   ܾ CART  cart_animal
reduce, work_animal reduceؾ ˰ ȴ.

)    ó  Ź ⸦ Ϸ Ѵ.
a = 2.3 + 3.5
b = 3.5 + 5.2
c = a + b - 1
c
= 13.5

   Ϸ ⺻ ҷ   ִ
ɺ̺ ϰ,  ɺ̺  ̸  ؾ Ѵ.
 ̸  ĺ ٰ  ׷  
̴.  
  
[ post ] % cat variable.y
%{
double vbltable[26];  /* double  迭 */
%}
%union  {
                double dval;
                int vblno;
         }
%token    <vblno> NAME
%token    <dval> NUMBER
%left '-' '+'
%left '*' '/'
%nonassoc UMINUS
%type <dval> expression
%%
statement_list: statement '\n'
          |         statement_list statement '\n'
          ;
statement:        NAME '=' expression  { vbltable[$1] = $3; }
          |   expression                 { printf("= %g\n",$1); }
          ;
expression: expression '+' expression  { $$ = $1 + $3;  }
          | expression '-' expression  { $$ = $1 - $3;  }
          | expression '*' expression  { $$ = $1 * $3;  }
          | expression '/' expression
                    {  if($3 == 0.0)
                             yyerror("divide by zero");
                       else   $$ = $1 /$3;
                    }
           |  '-'expression  %prec UMINUS   { $$ = -$2; }
           |  '('expression')'     { $$ = $2; }
           |       NUMBER
           |       NAME       { $$ = vbltable[$1]; }
           ;
%%
main()
{
    yyparse();
}


̸  ĺ  26 Ҹ  迭 vbltable[26]
ؼ   ϵ Ѵ.   %union lexer ޴ token
NAME NUMBER NAME vbltable[]  ε Īϰ Ͽ, 0 25 
 ϴ ݸ鿡, NUMBER Ǽ   Ѵ.  ,  
token̶
ϴ,   ٸ Ǵµ,   ޶,     

token νĵǱ ,  Ҹ ϵ   %union 
ϰ
ȴ.  ׸ %union , y.tab.cȿ C union ȯǾ óȴ.
"%type <dval> expression"  , token ƴ϶ token  

LHS 쿡 ˸ Ÿ  ϴٴ  ش.
"NAME '=' expression  { vbltable[$1] = $3; }"    
reduce 
 actionθ ϰ Ǵµ, ǹ̴ $1  NAME (0 25 

yylex()κ ޾Ҵ) vbltable  ҿ $3  expression  ִ 
̴.
  x = 2.0 + 3.2̾ x  $1 23 Ǹ vbltable[23] = 5.2 
ǹ̸
.   "'-' expression %prec UMINUS  {  $$ = -$2;  }"  -2  
ܾ
  - 2-3 - ƴ϶ %prec  ȣ - 켱 
 ξ
 ̷ ǹѴ.
"NAME    { $$ = vbltable[$1];  }"  y ̸ ־ $1  
0
25  ߿ 24° شǹǷ vbltable[24]  ÿ ϰ ȴ.

[ post ] % cat variable.l
%{
#include "y.tab.h"
#include <math.h>

extern double vbltable[26];
%}
%%
([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?)  {
                  yylval.dval = atof(yytext); return NUMBER;
                }
[\t]   ;        /* ignore white space */
[a-z]    {      yylval.vblno = yytext[0] - 'a'; return NAME; }
"$"      { return 0; }    /*  end of input  */
\n       |
.                return yytext[0];
%%

 lexȭ , yylval.dval ǥ  ִ , ̰ yylval
unionŸ  ǾǷ, NUMBER̸,  , 
yylval.dval Ͽ,   Ÿ.     ĺ
ϱ , ܼ 0 25  vbltable εϰ Ǵµ,
lex yylval.vblno = yytext[0] - 'a' yylval 0 25  ְ
ȴ.   α׷(variable.l  variable.y) Ͽ  
Ʒ .

[ post ] % yacc -d variable.y
[ post ] % lex variable.l
[ post ] % cc -o variable y.tab.c lex.yy.c -ll
[ post ] % ./variable
7.5+3.5
= 10
200/20+20/2
= 20
x=20/2
y=x+1
y
= 11


1.4 Lex Yacc ̿

  Lex Yacc ÿ Ͽ  ̴.

[ post ] % cat example.h
#define NOUN 257
#define PRONOUN 258
#define  VERB  259
#define  ADVERB  260
#define  ADJECTIVE  261
#define  PREPOSITION   262
#define  CONJUNCTION 263
[ post ] % cat example.l
%{
/*
 * build a lexical analyzer to be used by a high-level parser.
 */
#include "example.h" /* token codes from the parser */
#define LOOKUP 0 /* default - not a defined word type.  */
int state;

%}
%%

\n { state = LOOKUP; }
\.\n { state = LOOKUP; return 0; }  /*   ó  ǹ */
^verb { state = VERB;  }
^adj { state = ADJECTIVE; }
^adv { state = ADVERB; }
^noun { state = NOUN; }
^prep { state = PREPOSITION; }
^pron { state = PRONOUN; }
^conj { state = CONJUNCTION; }
[a-zA-Z]+ {
         if (state != LOOKUP) {
                add_word(state, yytext);
          } else {
                switch(lookup_word(yytext))
                {
                      case VERB  : return(VERB);
                      case ADJECTIVE : return(ADJECTIVE);
                      case ADVERB  : return(ADVERB);
                      case NOUN  : return(NOUN);
                      case PREPOSITION : return(PREPOSITION);
                      case PRONOUN : return(PRONOUN);
                      case CONJUNCTION : return(CONJUNCTION);
                      default   : printf("%s: don't reconize\n", yytext);
                                           /*  don't return just ignore it  */
                   }
             }
       }
.   ;

%%
/*  ܾ Ÿ Ͽ ܾ    ü  */
struct word {
        char *word_name;
        int  word_type;
        struct word *next;
};
struct word *word_list;
extern void *malloc();

int add_word(type, word)
int type; char *word;
{
        struct word *wp;
        if (lookup_word(word) != LOOKUP) {
                printf("!!! warning: word %s already defined \n",word);
                return 0;
        }

        /*  word not there, allocate a new entry and link it on the list */
        wp = (struct word *) malloc(sizeof(struct word));
        wp->next = word_list;
        /* have to copy the word itself as well */

        wp->word_name = (char *)malloc(strlen(word)+1);
        strcpy(wp->word_name, word);
        wp->word_type = type;
        word_list = wp;
        return 1;    /* it worked */
}

int lookup_word(word)
char *word;
{
        struct word *wp = word_list;
        /*  search down the list looking for the word  */
        for (; wp; wp = wp->next) {
                if (strcmp(wp->word_name, word) == 0)
                        return wp->word_type;
        }
        return LOOKUP; /*  not found  */
}

verb, noun  ؼ state ̿Ͽ,     ܾ 
ɺ̺ ϰ Ǵ  add_word()Լ̰  ϵ ܾ 캸 
Լ  lookup_word()̴.

 yaccȭ example.yȭ ̴.
[ post ] % cat example.y
%{
 /*
  A lexer for basic grammar to use for recognizing english sentences.
  */
#include <stdio.h>
%}
%token  NOUN PRONOUN VERB ADVERB ADJECTIVE PREPOSITION CONJUNCTION
%%
sentence: subject VERB object { printf("Sentence is valid.\n"); }
  ;
subject:  NOUN
  | PRONOUN
  ;
object:  NOUN
  ;
%%

extern FILE *yyin;
main()
{
  while(!feof(yyin)) {
     yyparse();
  }
}

yyerror(s)
char *s;
{
  fprintf(stderr,"%s\n",s);
}

 yaccȭϿ "%token NOUN PRONOUN VERB ADVERB ADJECTIVE PREPOSITION
CONJUNCTION" Է ⺻ ū óѴٴ  ǹϰ ⼭
lexerԼ Ѱܹ޴  ȴ.  , yyparse() Ź yylex() θ, 
  NOUN̳ PRONOUN  token  Ǵ ̴. 
  , yyparse ׷ ū    ´ мϿ, 
 ־, action C  ϰ ȴ.
yacc Է yyin̶ ȭϿ  ǰ,  yyout̶ ȭϷ
 ȴ.  ⺻δ yyin yyout stdin stdout,  ǥ ,
 ǾǷ, Ű ȭ   ̷ ȴ.  
̸ ٲپִ  տ Ͽ.
yyparse() yacc ִ м(parser)̰, yyerror() м
߿    θ Լ̴. 
   տ  lexȭ(example.l) yaccȭ(example.y) 
Ͽ  ̴.

[ post ] % lex example.l
[ post ] % yacc example.y
[ post ] % cc -o example lex.yy.c y.tab.c -ll
[ post ] % ./example
noun pig fish I
verb run am are
verb outrun
pig outrun fish
Sentence is valid.
noun you
you are pig
Sentence is valid.
pig are
syntax error
syntax error
pig outrun fish.
Sentence is valid.
verb am
!!! warning: word am already defined 
I am fish
Sentence is valid.
i am fish
i: don't reconize
syntax error


1.5 Makefile ̿
  ȭϰ, α׷   ϱ ؼ  
makefile Ͽ ϰ    ִ.

[ post ] % cat makefile
CC = cc
LIBS = -ll
LEX = lex
YACC = yacc
CFLAGS = -DYYDEBUG=1
all: speech
speech: y.tab.c lex.yy.c
                $(CC) -o speech y.tab.c lex.yy.c $(LIBS)
y.tab.c: example.y
                $(YACC) -d example.y
lex.yy.c : exaple.l
                $(LEX) example-07.l
[ post ] % make
cc -o speech y.tab.c lex.yy.c -ll


3. 
  lex & yacc - O'Reilly & Associates. Inc.


