· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Linuxdoc Sgml/Lex_Yacc-KLDP

<!doctype linuxdoc system>

<article>

<title>Lex & Yacc(¼Ò°³¿Í ¿¹Á¦ Áß½ÉÀ¸·Î)
<author>¹Ú ¼º±¸ <htmlurl url="mailto:byosmosis@yahoo.com" name="byosmosis@yahoo.com">
<date>1997³â 11¿ù 1ÀÏ
<abstract>
ÀÌ ±ÛÀº... ¾ðÁ¨°¡ ´©±º°¡¸¦ À§ÇØ ¸®Æ÷Æ®¸¦ ´ë½Å ÇØÁÖ´À¶ó°í ÀÛ¼ºÇß¾ú´ø
¹®¼­ÀÔ´Ï´Ù. ^^;  ÅØ½ºÆ®¿¡¼­ º¼ ¼ö ÀÖµµ·Ï ¹Ù²Ù¾î¼­ °Ô½ÃÇÕ´Ï´Ù. 
lex & yaccÀ» ¹è¿öº¸¼¼¿ä.  :) 

  Lex¿Í Yacc´Â ÀԷ±¸¹®ÀÇ °Ë»ö°ú ºÐ¼®À» ¿ëÀÌÇÏ°Ô Çϱâ À§ÇÏ¿© °³¹ßµÇ¾ú´Ù.
ÀԷ¿¡ ´ëÇÑ ¾î¶² ÆÐÅÏÀ» °®¾î¾ß ÇÏ´Â ÀÀ¿ë ÇÁ·Î±×·¥À» ¸¸µé ¶§ Á»´õ ºü¸£°í
Á¤È®ÇÏ°Ô ±×¸®°í ¾à°£ÀÇ ¼öÁ¤À¸·Î À¯Áöº¸¼ö°¡ ½±°Ô µÇ´Â °ÍÀÌ lex¿Í yaccÀÇ
Ư¡ÀÌ´Ù.  

    Lex¿Í Yacc°¡ ¾²ÀÌ´Â ¿¹·Î´Â ¼ýÀÚ¿Í ¿¬»êÀÚ¸¦ ±¸º°ÇØÁà¾ß ÇÏ´Â °è»ê±â,
ÄÄÆÄÀÏ·¯³ª ÀÎÅÍÇÁ¸®ÅÍ ¾ð¾îÀÇ ¹®Àå °Ë»ö, ¹®¹ý ºÐ¼®À» À§ÇÑ °ÍÀ̳ª, µ¥ÀÌŸ
º£À̽º¿¡¼­ÀÇ SQL¾ð¾îÀÇ ¹®¹ýÀ» üũÇÏ´Â °Í,  lex¸¸À» ÀÌ¿ëÇÑ ±¸ºÐ ºÐ¼® µîÀÇ
¿©·¯°¡Áö °æ¿ì¿¡ ÀÌ¿ëµÈ´Ù.
 
¿©±â¼­´Â lex¿Í yaccÀÇ Àü¹ÝÀûÀÎ ¼Ò°³¿Í lex¿Í yacc¸¦ ÀÌ¿ëÇÏ´Â ¹ý ±×¸®°í
¾à°£ÀÇ lex¿Í yaccÀÇ ÀÀ¿ë µî¿¡ ´ëÇØ¼­ ¼Ò°³ÇϰíÀÚ ÇÑ´Ù.
</abstract>
<toc>


<sect> Lex & Yacc<p>
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.)°¡ ÀÖ´Ù.


<sect1> LexÀÇ »ç¿ë(Lex¸¦ ÀÌ¿ëÇÑ °£´ÜÇÑ ÇÁ·Î±×·¥)<p>

¿¹Á¦)  Lex´Â ¾Æ·¡¿Í °°ÀÌ %%¿Í %%»çÀÌ¿¡´Â lex°¡ ±â¼úµÇ°í ±× ÀÌÈÄ¿¡´Â
       C°¡ ±â¼úµÈ´Ù.
<tscreen><verb>
%%
.|\n    ECHO;
%%
 
main()
{
        yylex();
}
</verb></tscreen>
 
À§´Â Ç¥ÁØÀÔ·ÂÀ» Ç¥ÁØÃâ·ÂÀ¸·Î ³»º¸³»´Â °¡Àå °£´ÜÇÑ lex ÇÁ·Î±×·¥À¸·Î Á¤±Ô
Ç¥Çö .¿Í \nÀ¸·Î Ç¥½ÃµÇ´Â ¹®ÀÚ°¡ µé¾î¿ÔÀ» ½Ã ±×´ë·Î ¿¡ÄÚÇØÁØ´Ù.  (½ÇÁ¦·Î
lex¿¡¼­ À§ÀÇ ³»¿ëÀº defaultÀÌ´Ù.) 

À¯¿ëÇÑ ´Ù¸¥ °£´ÜÇÑ ¿¹·Î ´ÙÀ½°ú °°Àº
<tscreen><verb>
 [\t ]+          ;       # whitespace¸¦ ¹«½ÃÇÑ´Ù
</verb></tscreen>
¸¦ %%¿Í %%»çÀÌ¿¡ Æ÷ÇÔ½Ã۸é ÅÇÀ̶óµç°¡ Çϳª ÀÌ»óÀÇ °ø¹éÀÌ ÀÖ´Â °æ¿ì C¿¡¼­¿Í
¸¶Âù°¡Áö·Î ¾Æ¹« 󸮵µ ¾ÈÇØÁÖ´Â ';'¸¦ »ç¿ëÇÏ¿´±â ¶§¹®¿¡ ¾Æ¹« 󸮵µ ÇÏÁö
¾Ê´Â´Ù.(È­¸é¿¡ °°Àº ¸Þ½ÃÁö¸¦ ¿¡ÄÚÁ¶Â÷µµ ÇÏÁö ¾Ê´Â´Ù.)
 
À§ÀÇ ¼Ò½º¸¦ simple.lÀ̶ó°í Çϸé(¹ØÁ٠ǥ½Ã´Â »ç¿ëÀÚ ÀÔ·Â)
<tscreen><verb>
[ 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();
}
</verb></tscreen>

À§¿Í °°ÀÌ µÇ¾î UNIXÀÇ cat°ú  À¯»çÇÑ ÇÁ·Î±×·¥ÀÌ ¿Ï¼ºµÈ´Ù.(ÀÎÀÚ°¡ ¾ø´Â
cat ¸í·ÉÀÇ »ç¿ë½Ã ½ÇÁ¦·Î À§ÀÇ ÇÁ·Î±×·¥°ú °°´Ù)

¡Ø lexÀÇ ±¸¼ºÀº ´ÙÀ½ ¼¼°¡Áö definitions, rules, user code sectionÀ¸·Î
   ÀÌ·ç¾îÁø´Ù.

<tscreen><verb>
definitions 
  # rules¿¡ patternÀ» °£´ÜÇÏ°Ô Çϱâ À§ÇÑ ¼±¾ð°ú Ãʱâ Á¶°Ç
  # CÄÚµå »ðÀԽà %{, }% ±âÈ£¸¦ Ç¥½ÃÇÏ°í »çÀÌ¿¡ ¾µ ¼ö ÀÖÀ½
%%
rules  
  # pattern°ú actionÀ¸·Î ÀÌ·ç¾îÁü
  # CÄÚµå´Â {, }·Î °¨½Î¼­ Ç¥½ÃÇÔ
%%
user code 
  # yylex()ÇÔ¼ö¿Í »ç¿ëÀÚ°¡ ¿øÇÏ´Â C ·çƾÀ¸·Î ÀÌ·ç¾îÁü
</verb></tscreen>


¿¹Á¦)

¶Ç %%¿Í %%»çÀÌ¿¡ lex¸¦ ±â¼úÇϱâ ÀÌÀü¿¡ C¸¦ ±â¼úÇϱ⸦ ¿øÇҽÿ¡´Â
 %{¿Í %}·Î CÀÇ ±â¼úÀ̶ó´Â Ç¥½Ã¸¦ ÇÏ°í ±× »çÀÌ¿¡ ±â¼úÇÒ ¼ö ÀÖ´Ù.
 
<tscreen><verb>
%{
        /*
         * 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();
}
</verb></tscreen>

yytext´Â lex¿¡¼­ »ç¿ëµÇ´Â ÀÔ·Â ÅØ½ºÆ®¿¡ ´ëÇÑ global character pointerÀÌ´Ù.
À§ÀÇ ¼Ò½º¸¦ simple.l°ú °°Àº ¹æ¹ýÀ¸·Î ÄÄÆÄÀÏÇÏ¿© ½ÇÇà½ÃÄÑ º¸¸é

<tscreen><verb>
[ 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. ^_~
</verb></tscreen>

À§¿¡ ³ªÅ¸³­ ¼öÇà°á°úÀÇ Ãâ·Â°ú °°ÀÌ Ã³¸®Çϱ⸦ ¿øÇÏ´Â ÆÐÅÏ¿¡ ´ëÇØ¼­ 󸮰¡
ÀÌ·ç¾îÁø´Ù.  love7ÀÇ °æ¿ì¿¡´Â love¿¡ ´ëÇÑ Ã³¸®¸¦ ÇØÁÖ°í 7Àº ¾ËÆÄºªÀÌ ¾Æ´Ï¹Ç·Î
´ÙÀ½ÁÙ¿¡ ¿¡ÄÚ°¡ µÈ´Ù.
¶Ç °á°úÁß ¹Ù·Î À§ÀÇ 'love story'´Â love¸¦ ÀνÄÇϰí whitespace·Î ºóÄ­À» 
ÀνÄÇϰí
´ÙÀ½¿¡ story¸¦ ÀνÄÇÑ °ÍÀÌ´Ù.  µû¶ó¼­ love¿¡ ´ëÇÑ Ã³¸®¿Í ºóÄ­¿¡ ´ëÇÑ ¾Æ¹«
󸮾øÀ½°ú story¿¡ ´ëÇÑ Ã³¸®°¡ °á°ú ³»¿ëÀÌ µÉ °ÍÀÌ´Ù.
À§ÀÇ ¿¹·Î¼­ loveyou¶ó°í ÀÔ·ÂÀ» Çß´Ù¸é love ´ÙÀ½¿¡ you¸¦ µû·Î º¸´Â °ÍÀÌ ¾Æ´Ï¶ó
ÇϳªÀÇ ÆÐÅÏÀ¸·Î º¸¾Æ distress¿Í °°Àº °á°ú°¡ ³ª¿Ã °ÍÀÓÀ» ¿¹»óÇÒ ¼ö ÀÖ´Ù.


¿¹Á¦) ´ÙÀ½Àº ÀüÀÇ ¿¹Á¦¿Í °°Àº °£´ÜÇÑ Çü½ÄÀ¸·Î ´Ù¸¸ ¼ýÀÚ¿¡ ´ëÇÑ CÀÇ 
enumÇü½ÄÀ¸·Î
      ¼±¾ðÇÏ¿© ½Éº¼ Å×À̺íÀÇ °ªÀ» ÀÌ¿ëÇÏ´Â ¿¹¸¦ º¸¿©ÁØ´Ù.

<tscreen><verb>
[ 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
</verb></tscreen>

À§ÀÇ ¸¶Áö¸· 'two two'´Â two¿¡ ´ëÇÑ Ã³¸®¸¦ ÇØÁÖ°í ' 'ÀÇ ºóÄ­Àº ´ÙÀ½ ÁÙ¿¡
´Ü¼øÈ÷ ¿¡ÄÚÇØÁÖ°í ´ÙÀ½ÁÙ·Î ³Ñ¾î°¡Áö ¾Ê°í ´ÙÀ½ÀÇ two°¡ ó¸®µÇ¾î ³ªÅ¸³­
°á°úÀÌ´Ù. µû¶ó¼­ µÎ ¹øÂ°ÀÇ two¿¡´Â ¾Õ¿¡ ºóÄ­ÀÌ Çϳª ´õ ÀÖ´Ù.
±×¸®°í oneoneÀ̶ó´Â ÆÐÅÏÀÌ Á¸ÀçÇÒ ¶§¿¡´Â oneÀÇ ÆÐÅÏÀÌ ¾Æ´Ñ oneoneÀÇ ÆÐÅÏÀ»
µû¸£´Â °ÍÀº ±ä ¹®ÀÚ¿­ÀÌ ¿ì¼±¼øÀ§¸¦ °¡Áö±â ¶§¹®ÀÌ´Ù.(Á¤±Ô Ç¥Çö½Ä ÂüÁ¶)


¿¹Á¦) ´ÙÀ½Àº lexÀÇ À§¿¡ Á¦½ÃÇÑ °Íº¸´Ù ¾à°£ º¹ÀâÇÑ ¼ýÀÚ¿Í ¿¬»êÀÚ¿Í º¯¼ö¸¦
      ÀνÄÇÏ´Â ¿¹Á¦·Î¼­ Á¶±Ý¸¸ °³¼±½ÃŰ¸é ¿ÏÀüÇÑ °è»ê±â ÇÁ·Î±×·¥ÀÌ µÉ ¼ö
      ÀÖ´Ù.  ÀÌ ¿¹Á¦´Â ´Ü¼øÈ÷ ¼ýÀÚÀÎÁö, ¿¬»êÀÚÀÎÁö, ¿¹¾à¾î ¶Ç´Â º¯¼ö·Î¼­
      »ç¿ëµÉ °ªÀÎÁö¸¦ Ãâ·ÂÇÏ¿© ³ªÅ¸³»µµ·Ï ÇÏ´Â ¿¹Á¦ÀÌ´Ù.

<tscreen><verb>
%{
/* 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();
}
</verb></tscreen>

À§ÀÇ ¿¹¿¡¼­ yyin¿¡ ´ëÇÑ ÁöÁ¤Àº ÀÔ·ÂÀ» Ä¿¸Çµå ¶óÀλóÀÇ Ã¹ÀÎÀÚ°¡ °¡¸®Å°´Â
ÆÄÀÏÀÇ ³»¿ëÀ» ó¸®ÇÒ °ÍÀÌÁö È­¸é¿¡¼­ Ç¥ÁØÀÔ·ÂÀ» ¹Þ¾Æ ó¸®ÇÒ °ÍÀÎÁö¿¡ ´ëÇÑ
󸮸¦ ÇÒ ¼ö ÀÖ°Ô ÇÑ´Ù.



<sect1> Lex¿Í YaccÀÇ °ü°è(Lex scanner, Yacc parser)<p>

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¿¡ ´ëÇÑ °Ë»ö ¿£Áø µî¿¡ ÀÌ¿ëÇÒ ¼ö ÀÖ°Ôµµ ÇÏ¿´´Ù.


<sect1> YaccÀÇ »ç¿ë<p>

  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ÀÇ ±¸Á¶¸¦ º»µû ¾´ °ÍÀÌ´Ù.

<tscreen><verb>
definitions 
   # CÄÚµå »ðÀԽà %{, }% ±âÈ£·Î Ç¥½ÃÇÏ°í »çÀÌ¿¡ ¾µ ¼ö ÀÖÀ½
%%
rules 
   # °¢ ruleÀº "LHS: RHS;"¿Í °°Àº Çü½ÄÀ¸·Î ÀÌ·ç¾îÁü
%%
user code
   # lex¿ÍÀÇ °áÇսà yylex()¸¦ ÀÌ¿ëÇÑ´Ù.

¡Ø LHS´Â left-hand symbolÀÇ ¾àÀÚ·Î ':'ÀÇ ¿ÞÂÊ¿¡ ¿À´Â statement,
   expression°ú °°ÀÌ ¿ÞÂÊ¿¡ ¿À´Â ±âÈ£¸¦ ¸»Çϸç,  RHS´Â right-hand
   symbolÀÇ ¾àÀÚ·Î ':'ÀÇ ¿À¸¥ÂÊ¿¡ ¿À´Â ±âÈ£¸¦ ¸»ÇÑ´Ù.
   °¢ ruleÀÇ ³¡Àº ';'À¸·Î Ç¥½ÃÇÑ´Ù.
</verb></tscreen>

¿¹Á¦) yaccÀÇ ÀÌÇØ¸¦ À§ÇÑ °£´ÜÇÑ ´ÜÁö µ¡¼À°ú »¬¼À¸¸ÀÌ °¡´ÉÇÑ ¾ÆÁÖ °£´ÜÇÑ
      ±â´ÉÀ» °¡Áø °è»ê±â¸¦ ¸¸µç´Ù°í ÇÒ ¶§ ±×°ÍÀÇ ½ÇÁ¦ ½ÇÇà ¿¹¸¦ º¸À̸é
       ¾Æ·¡¿Í °°´Ù.

<tscreen><verb>
[ 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];
%%
</verb></tscreen>

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)À» ÄÄÆÄÀÏÇÏ¿© ½ÇÇàÇÑ °á°ú´Â ¾Æ·¡¿Í °°´Ù. 
<tscreen><verb>
[ 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
</verb></tscreen>

¿©±â¼­´Â y.tab.h¸¦ lexer¿¡¼­ includeÇϱ⠶§¹®¿¡, yacc¿¡¼­ ¸¸µé¾îÁÖ±â À§ÇØ
-d ½ºÀ§Ä¡¸¦ ÀÌ¿ëÇÏ¿´´Ù. lex¸¦ ÀÌ¿ëÇÏ¿©, lex.yy.c¸¦ ¸¸µé°í, yaccÀ» ÀÌ¿ëÇÏ¿©,
y.tab.c¸¦ ¸¸µé¾î¼­ liby.a¿Í libl.a¸¦ ¸µÅ©ÇÏ¿© ¿øÇÏ´Â ½ÇÇàÈ­ÀÏÀ» ¸¸µé°Ô µÈ´Ù.

¡Ø Yacc¿¡¼­ÀÇ ¸ðÈ£¼º  - ´ÙÀ½°ú °°Àº ¿¹Á¦¸¦ »ý°¢Çغ¸ÀÚ.
<tscreen><verb>
expression : expression '+' expression
    |        expression '-' expression
    |        expression '*' expression
    |        expression '/' expression
    |        '-' expression
    |        '(' expression ')'
    |        NUMBER
</verb></tscreen>
  À§ÀÇ 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¸¦ ÇØ°áÇÑ °ÍÀº ¾Æ·¡¿Í °°´Ù.
<tscreen><verb>
expression: expression '+' mulexp
  |   expression '-' mulexp
  |   mulexp
  ;
mulexp : mulexp '*' primary
  |   mulexp '/' primary
  |   primary
  ;
primary:  '(' expression ')'
  |   '-' primary
  |   NUMBER
  ;
</verb></tscreen>
¹®Á¦¸¦ ÇØ°áÇÏ´Â ¶Ç´Ù¸¥ ¹æ¹ýÀ¸·Î yacc¿¡¼­ Á¦°øÇÏ´Â ¸í·É¾î¸¦ ÀÌ¿ëÇÏ´Â ¹æ¹ýÀ¸·Î
ÀÌ ¸í·É¾î¸¦ ÀÌ¿ëÇØ¼­, ¿ì¼±¼øÀ§ ¹× °áÇÕ¹ýÄ¢À» Á¦°øÇÒ ¼ö ÀÖ°Ô µÈ´Ù. ¸î°¡Áö
À¯¿ëÇÑ ¸í·ÉÀÇ ¿¹¸¦ µé¾îº¸¸é ´ÙÀ½°ú °°´Ù.

<tscreen><verb>
%left  '+' '-'
%left  '*' '/'
%right '='
%nonassoc  UMINUS /* unary operatorÀÇ Á¤ÀÇ·Î °áÇÕ¹ýÄ¢ÀÌ Àû¿ëÀÌ ¾ÈµÈ´Ù.  */
</verb></tscreen>

À§¿Í °°ÀÌ ±â¼úÇÏ°Ô µÇ¸é, + - * / = ÀÇ ¿ì¼±¼øÀ§´Â + - °¡ °¡Àå ³·°í, * /°¡
±×°Íº¸´Ù ³ô°í, ´ëÀÔ¿¬»êÀÚ = ÀÌ ³ô°í, ºÎÈ£¿¬»êÀÚÀÎ -°¡ °¡Àå ³ôÀº ¿ì¼±¼øÀ§¸¦
°¡Áø´Ù´Â °ÍÀ» º¸¿©ÁÖ°í ÀÖ´Ù.  ¶ÇÇÑ +³ª -, *, /´Â ¿ÞÂÊÀ¸·Î °áÇÕ¹ýÄ¢À» °¡Áö°í,
´ëÀÔ¿¬»êÀÚ =´Â ¿ìÃøÀ¸·Î °áÇÕ¹ýÄ¢À» µû¸¥´Ù.

<tscreen><verb>
%token NAME NUMBER
%left '-' '+'
%left '*' '/'
%nonassoc UMINUS
expression:     expression '+' expression
         |      expression '-' expression
         |      expression '*' expression
         |      expression '/' expression
         |      '-' expression %prec UMINUS
         |      '(' expression ')'
         |      NUMBER
         ;
</verb></tscreen>
À§¿¡¼­ Áß°£¿¡ º¸ÀÌ´Â %prec UMINUS´Â '-' expression°ú °°Àº ¹®ÀÚ¿­À» ÆÄ½ÌÇϰÔ
µÇ¸é -¿¡ ´ëÇØ¼­´Â UMINUS·Î ÁöÁ¤µÈ ¿ì¼±¼øÀ§¸¦ »ç¿ëÇ϶ó´Â ÀǹÌÀÌ´Ù.  
µû¶ó¼­, ¸ðÈ£ÇÑ ¹®¹ý¿¡¼­ º¸ÀÌ´Â shift/reduce conflict°¡ »ý±æ¶§, ¿ì¼±¼øÀ§¿Í 
°áÇÕ¹ýÄ¢À» Àû¿ëÇÔÀ¸·Î½á, ½±°Ô ÇØ°áÇÒ ¼ö°¡ ÀÖ°Ô µÈ´Ù.

¡Ø ¶Ç´Ù¸¥ YaccÀÇ ¸ðÈ£¼º, LALR(1)ÀÌ ¾Æ´Ñ ¹®¹ýÀÇ ¿¹
´ÙÀ½°ú °°Àº ¹®¹ýÀ» »ìÆìº¸ÀÚ.

<tscreen><verb>
phrase: cart_animal AND CART
        | work_animal  AND PLOW
cart_animal: HORSE | GOAT
work_animal: HORSE | OX
</verb></tscreen>

À§ÀÇ ¿¹´Â µé¾î, 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)¹®¹ýÀ¸·Î ¹Ù²Ù¾î ÁÖ¾î¾ß ÇÑ´Ù.

<tscreen><verb>
phrase -> cart_animal  CART
         | work_animal  PLOW
cart_animal  -> HORSE | GOAT
work_animal -> HORSE | OX
</verb></tscreen>

 À§ÀÇ ¹®¹ýÀº HORSE¸¦ º¸°í, ¹Ù·Î µÚÀÇ ÇÑ ´Ü¾îÀÎ CART¸¸À» º¸¸é cart_animal·Î
reduceÇÒÁö, work_animal·Î reduceÇØ¾ßÇÒÁö¸¦ ¾Ë°Ô µÈ´Ù.

¿¹Á¦) ´ÙÀ½°ú °°ÀÌ º¯¼ö 󸮰¡ °¡´ÉÇÑ Å¹»ó °è»ê±â¸¦ ±¸ÇöÇÏ·Á°í ÇÑ´Ù.
<tscreen><verb>
a = 2.3 + 3.5
b = 3.5 + 5.2
c = a + b - 1
c
= 13.5
</verb></tscreen>

À§¿Í °°Àº ±â´ÉÀ» ¼öÇàÇÏ·Á¸é ±âº»ÀûÀ¸·Î ±â¾ïÀå¼Ò·Î »ç¿ëµÉ ¼ö ÀÖ´Â
½Éº¼Å×À̺íÀ» À¯ÁöÇϰí,  ½Éº¼Å×ÀÌºí¿¡ º¯¼öÀÇ À̸§°ú °ªÀ» À¯ÁöÇØ¾ß ÇÑ´Ù.
´ÙÀ½Àº º¯¼öÀ̸§ÀÌ ¿µ¹®ÀÇ ¾ËÆÄºª¸¸À» °¡Áø´Ù°í °¡Á¤ÇÑ ±×·¯ÇÑ ¿¹¸¦ º¸ÀÎ
°ÍÀÌ´Ù.  
  
<tscreen><verb>
[ 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();
}

</verb></tscreen>

º¯¼öÀ̸§ÀÌ ¿µ¹®ÀÇ ¾ËÆÄºª¸¸À» °¡Áø 26°³ÀÇ ¿ø¼Ò¸¦ °¡Áø ¹è¿­ÀÎ vbltable[26]À»
¼±¾ðÇØ¼­ º¯¼öÀÇ °ªÀ» À¯ÁöÇϵµ·Ï ÇÑ´Ù.  À§¿¡¼­ %unionÀº lexer¿¡¼­ ¹Þ´Â tokenÀÎ
NAME°ú NUMBER¸¦ NAMEÀº vbltable[]ÀÇ ÇÑ À妽º¸¦ ÁöĪÇÏ°Ô ÇÏ¿©, 0ºÎÅÍ 25ÀÇ °ªÀ»
°¡Áö°Ô ÇÏ´Â ¹Ý¸é¿¡, NUMBER´Â ½Ç¼öÀÇ °ªÀ» °¡Áöµµ·Ï ÇÑ´Ù.  µû¶ó¼­, °°Àº 
tokenÀ̶ó°í
ÇÏ´õ¶óµµ, °¡Áö´Â °ªÀÌ ´Ù¸£°Ô µÇ´Âµ¥, °¡Áö´Â °ªÀº ´Þ¶óµµ, ÇÑ ¼ø°£¿¡´Â ¿ÀÁ÷ ÇÑ 
°³ÀÇ
token¸¸ÀÌ ÀνĵDZ⠶§¹®¿¡, °°Àº ±â¾ïÀå¼Ò¸¦ À¯ÁöÇϵµ·Ï À§¿Í °°ÀÌ %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]ÀÇ °ªÀ» ½ºÅÿ¡ ÀúÀåÇÏ°Ô µÈ´Ù.

<tscreen><verb>
[ 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];
%%
</verb></tscreen>

À§ÀÇ lexÈ­ÀÏÀ» º¸¸é, yylval.dval·Î Ç¥ÇöÇÑ °ÍÀÌ ÀÖ´Â µ¥, À̰ÍÀº yylval°¡
unionŸÀÔÀ¸·Î ¼±¾ðÀÌ µÇ¾îÀÖÀ¸¹Ç·Î, NUMBERÇüÀ̸é, °ªÀ» ³ÖÀ»¶§¿¡µµ, 
yylval.dval½ÄÀ¸·Î ÇÏ¿©, ³ÖÀ¸¶ó´Â °ÍÀ» ³ªÅ¸³½´Ù.  ¶ÇÇÑ º¯¼ö°¡ ¿µ¹® ¾ËÆÄºª¸¸À»
°¡Á¤Çϱ⠶§¹®¿¡, ´Ü¼øÈ÷ 0ºÎÅÍ 25»çÀÌÀÇ °ªÀ¸·Î vbltableÀ» À妽ÌÇÏ°Ô µÇ´Âµ¥,
lex¿¡¼­ÀÇ yylval.vblno = yytext[0] - 'a'´Â yylval¿¡ 0ºÎÅÍ 25»çÀÌÀÇ °ªÀ» ³Ö°Ô
µÈ´Ù.  À§ÀÇ ÇÁ·Î±×·¥(variable.l °ú variable.y)À» ÄÄÆÄÀÏÇÏ¿© ½ÇÇàÇÑ °á°ú´Â
¾Æ·¡¿Í °°´Ù.

<tscreen><verb>
[ 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
</verb></tscreen>


<sect1> Lex¿Í YaccÀÇ ÀÌ¿ë<p>

´ÙÀ½Àº ½ÇÁ¦·Î Lex¿Í Yacc¸¦ µ¿½Ã¿¡ °áÇÕÇÏ¿© »ç¿ëÇÑ ¿¹ÀÌ´Ù.

<tscreen><verb>
[ 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></tscreen>

verb, noun µî¿¡ ´ëÇØ¼­ state¸¦ ÀÌ¿ëÇÏ¿©, ÁÙÀÌ ³¡³ª±â Àü±îÁö ³ª¿À´Â ´Ü¾îµéÀ» 
½Éº¼Å×ÀÌºí¿¡ µî·ÏÇÏ°Ô µÇ´Â °ÍÀÌ add_word()ÇÔ¼öÀÌ°í ±× µî·ÏµÈ ´Ü¾î¸¦ »ìÆìº¸´Â 
ÇÔ¼ö°¡  lookup_word()ÀÌ´Ù.

´ÙÀ½Àº yaccÈ­ÀÏ example.yÈ­ÀÏÀÇ ³»¿ëÀÌ´Ù.
<tscreen><verb>
[ 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);
}
</verb></tscreen>

À§ÀÇ yaccÈ­ÀÏ¿¡¼­ &dquot;%token NOUN PRONOUN VERB ADVERB ADJECTIVE PREPOSITION
CONJUNCTION&dquot;¹®Àº ÀÔ·Â ±âº»´ÜÀ§ÀÎ ÅäÅ«À¸·Î ó¸®ÇÑ´Ù´Â °ÍÀ» ÀǹÌÇÏ°í ¿©±â¼­´Â
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)À» ½ÇÁ¦
ÄÄÆÄÀÏÇÏ¿© ¼öÇàÇÑ °á°úÀÌ´Ù.

<tscreen><verb>
[ 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

</verb></tscreen>

<sect1> MakefileÀÇ ÀÌ¿ë<p>
ÄÄÆÄÀÏ ÀýÂ÷¸¦ °£¼ÒÈ­Çϰí, ÇÁ·Î±×·¥ º¸¼ö¸¦ ½±°Ô Çϱâ À§Çؼ­ ´ÙÀ½°ú °°ÀÌ
makefile¸¦ Á¤ÀÇÇÏ¿© Æí¸®ÇÏ°Ô ÄÄÆÄÀÏÀ» ¼öÇàÇÒ ¼ö ÀÖ´Ù.

<tscreen><verb>
[ 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

</verb></tscreen>

<sect> Âü°íµµ¼­<p>
<itemize>
<item> lex & yacc - O'Reilly & Associates. Inc.
</itemize>
</article>




sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2008-12-13 12:17:49
Processing time 0.0018 sec