목차
1. Yacc Specification
2. Yacc grammar
3. Lex and Yacc for The Calculator
4. yacc와 lex간의 인터페이스
5. 실 행 결 과
2. Yacc grammar
3. Lex and Yacc for The Calculator
4. yacc와 lex간의 인터페이스
5. 실 행 결 과
본문내용
도 그대로 복사된다. 다음은 y.tab.h에서 %union에 대응하는 코드이다
typdef union {
double dval;
int vblno;
} YYSTYPE;
extern YYSTYPE yyval;
여기서 yyval는 token과 관련된 value을 저장하는 변수이다.
symbol의 type에 대한 선언을 하는 방법은 두 가지가 있다. token(terminal symbol)은 %token을 사용하여 type을 지정하며, non-terminal token의 type은 %type을 사용하여 지정한다.
rule을 정의하는 부분에서 보면 action에서 right-hand side의 끝에 ‘$’로 나타내는 부분이 있다. 이것은 action code내에서의 rule symbol의 참조를 의미한다.
$$ : rule의 left-hand side의 symbol
$1,$2,... : rule의 right-hand side의 첫번째 위치의 symbol,
2번째 위치의 symbol
yacc가 reduction시에 기본적으로 명시적인 action code를 수행하기 이전에 left-hand side의 symbol($$)에 값을 $1할당하므로 위의 { $$ = $1; }는 엄격히 말해 기술해주지 않아도 된다.
symlook( )은 symbol table에서 token에 해당하는 entry를 찾아 pointer를 반환시켜주는 역할을 하는데, strdup( )이 하는 역할은 token을 받아 들였을 때, symbol table에 없으면 새롭게 name string을 추가하는 역할을 한다.
생성될 parser code의 뒤로 그대로 복사되어질 C code로 보통은 main( ) 내에서 lex input file 인 yyin으로부터 token을 읽어들어 grammar rule에 따라 parsing하는 syntax analyzer인 yyparser( )를 호출한다. 즉, yyparse( )는 yacc에 의해 생성되는 parser의 C routine이다.
③ cal_lex.l
%{
#include "cal_yacc.h"
#include "cal.h"
#include
%}
%%
([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) { //float type의 token일 경우
yylval.dval = atof(yytext); // 형변환 명시
return NUMBER;
}
[ \t] ; // whitespace를 무시한다.
[A-Za-z][A-Za-z0-9]* { // symbol table point를 return한다.
struct symtab *sp = symlook(yytext);
yylval.symp = sp;
return NAME;
}
"$"{ return 0; }
\n|
.return yytext[0];
%%
lexer는 token에 관련된 type으로 자동적으로 변환해주지 못하므로 yylval에 값을 할당할 때는 반드시 명시적인 field reference와 값의 변환이 필요하다. lexer에서 float type값을 return하는 경우에 C의 atof( )를 사용하여 형 변환을 명시적으로 하고 있다.
4. yacc와 lex간의 인터페이스
지금까지 설명한 lex와 yacc를 동시에 사용하는 경우, 서로 간의 interface에 대해 정리를 하면 다음과 같다.
lex가 생성한 lexical analyzer인 yylex( )와 yacc가 생성하는 syntax analyzer인yyparse( )를 함께 사용하는 경우, yacc는 lex위의 단계에 위치하며 token이 필요한 경우에 yylex( )를 호출하고, yylex( )는 주어진 입력을 scanning하면서 token을 인식한다. yyparse( )가 필요로 하는 token인 경우에 yyparse()로 return되며 token ID가 yylex( )의 return value로 사용된다. 그러므로 lexer와 yacc parser는 사용하는 token ID를 일치시켜야 한다.
입력의 logical end시에는 yylex( )는 zero를 return한다. yacc는 모든 token의 정의를 포함하는 C header file( y.tab.h)을 작성하는데 이를 lexer내에 include시키고 lexer action code내에서 token ID를 return value로 사용하여야 한다.
1) yacc와 lex간의 token ID를 공유하기 위해서는 다음과 같은 과정이 필요하다.
① lex specification과 yacc specification화일이 있을 때
calculator.l : lex specification file
calculator.y : yacc specification file
② calculator.l에 verbatim copied영역에 bison이 생성할 token ID에 대한
정의가 포함된 calculator.tab.h파일을 include하는 코드를 추가한다.
③ calculator.y 파일에서는 사용한 token들을 기술한다.
필요한 경우 %union에서 선언한 데이터형을 추가하여 기술한다.
calculator.y를 yacc의 -d 옵션을 사용하여 yyparser( )가 포함된 syntax -
analyzer인 C code를 생성하면 다음과 같이 y.tab.h라는 이름을 가진 header
file이 생성된다.
④ lex와 yacc가 결합되어 사용되는 경우 다음과 같이 먼저 yacc speficication
file로부터 y.tab.h(%union 및 %token에 대한 정의가 포함된 C header file)와
y.tab.c (yyparse( )가 포함된 file)를 생성하고, lex specification file로부터
lexical analzer가 포함된 lex.yy.c를 생성하여야 한다.
5. 실 행 결 과
여기서 lex와 yacc를 이용해 만든 calculator는 사칙연산 외에도 log, square root, exponential을 계산할 수 있으며, 문자에 숫자를 주어 문자끼리 사칙연산을 하면 숫자로서 결과가 나오도록 되어있다.
typdef union {
double dval;
int vblno;
} YYSTYPE;
extern YYSTYPE yyval;
여기서 yyval는 token과 관련된 value을 저장하는 변수이다.
symbol의 type에 대한 선언을 하는 방법은 두 가지가 있다. token(terminal symbol)은 %token을 사용하여 type을 지정하며, non-terminal token의 type은 %type을 사용하여 지정한다.
rule을 정의하는 부분에서 보면 action에서 right-hand side의 끝에 ‘$’로 나타내는 부분이 있다. 이것은 action code내에서의 rule symbol의 참조를 의미한다.
$$ : rule의 left-hand side의 symbol
$1,$2,... : rule의 right-hand side의 첫번째 위치의 symbol,
2번째 위치의 symbol
yacc가 reduction시에 기본적으로 명시적인 action code를 수행하기 이전에 left-hand side의 symbol($$)에 값을 $1할당하므로 위의 { $$ = $1; }는 엄격히 말해 기술해주지 않아도 된다.
symlook( )은 symbol table에서 token에 해당하는 entry를 찾아 pointer를 반환시켜주는 역할을 하는데, strdup( )이 하는 역할은 token을 받아 들였을 때, symbol table에 없으면 새롭게 name string을 추가하는 역할을 한다.
생성될 parser code의 뒤로 그대로 복사되어질 C code로 보통은 main( ) 내에서 lex input file 인 yyin으로부터 token을 읽어들어 grammar rule에 따라 parsing하는 syntax analyzer인 yyparser( )를 호출한다. 즉, yyparse( )는 yacc에 의해 생성되는 parser의 C routine이다.
③ cal_lex.l
%{
#include "cal_yacc.h"
#include "cal.h"
#include
%}
%%
([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) { //float type의 token일 경우
yylval.dval = atof(yytext); // 형변환 명시
return NUMBER;
}
[ \t] ; // whitespace를 무시한다.
[A-Za-z][A-Za-z0-9]* { // symbol table point를 return한다.
struct symtab *sp = symlook(yytext);
yylval.symp = sp;
return NAME;
}
"$"{ return 0; }
\n|
.return yytext[0];
%%
lexer는 token에 관련된 type으로 자동적으로 변환해주지 못하므로 yylval에 값을 할당할 때는 반드시 명시적인 field reference와 값의 변환이 필요하다. lexer에서 float type값을 return하는 경우에 C의 atof( )를 사용하여 형 변환을 명시적으로 하고 있다.
4. yacc와 lex간의 인터페이스
지금까지 설명한 lex와 yacc를 동시에 사용하는 경우, 서로 간의 interface에 대해 정리를 하면 다음과 같다.
lex가 생성한 lexical analyzer인 yylex( )와 yacc가 생성하는 syntax analyzer인yyparse( )를 함께 사용하는 경우, yacc는 lex위의 단계에 위치하며 token이 필요한 경우에 yylex( )를 호출하고, yylex( )는 주어진 입력을 scanning하면서 token을 인식한다. yyparse( )가 필요로 하는 token인 경우에 yyparse()로 return되며 token ID가 yylex( )의 return value로 사용된다. 그러므로 lexer와 yacc parser는 사용하는 token ID를 일치시켜야 한다.
입력의 logical end시에는 yylex( )는 zero를 return한다. yacc는 모든 token의 정의를 포함하는 C header file( y.tab.h)을 작성하는데 이를 lexer내에 include시키고 lexer action code내에서 token ID를 return value로 사용하여야 한다.
1) yacc와 lex간의 token ID를 공유하기 위해서는 다음과 같은 과정이 필요하다.
① lex specification과 yacc specification화일이 있을 때
calculator.l : lex specification file
calculator.y : yacc specification file
② calculator.l에 verbatim copied영역에 bison이 생성할 token ID에 대한
정의가 포함된 calculator.tab.h파일을 include하는 코드를 추가한다.
③ calculator.y 파일에서는 사용한 token들을 기술한다.
필요한 경우 %union에서 선언한 데이터형을 추가하여 기술한다.
calculator.y를 yacc의 -d 옵션을 사용하여 yyparser( )가 포함된 syntax -
analyzer인 C code를 생성하면 다음과 같이 y.tab.h라는 이름을 가진 header
file이 생성된다.
④ lex와 yacc가 결합되어 사용되는 경우 다음과 같이 먼저 yacc speficication
file로부터 y.tab.h(%union 및 %token에 대한 정의가 포함된 C header file)와
y.tab.c (yyparse( )가 포함된 file)를 생성하고, lex specification file로부터
lexical analzer가 포함된 lex.yy.c를 생성하여야 한다.
5. 실 행 결 과
여기서 lex와 yacc를 이용해 만든 calculator는 사칙연산 외에도 log, square root, exponential을 계산할 수 있으며, 문자에 숫자를 주어 문자끼리 사칙연산을 하면 숫자로서 결과가 나오도록 되어있다.
추천자료
- DTD에 관한 모든것
- 자바 기반의 보안 프로그래밍
- 에이다 [Ada]프로그래밍언어
- 병렬 프로그램
- [레포트]프로그래밍
- C/C++로 제작한 지뢰찾기
- [자바][JAVA][자바스크립트]자바(JAVA)의 의미, 자바(JAVA)의 특징, 자바(JAVA)의 유래, 자바...
- c로 쓴 자료구조론 연습문제 7장(정렬sorting)
- 2011년 2학기 컴퓨터구조 기말시험 핵심체크
- 리눅스(Linux)에 대하여 [A+] .PPT자료
- 파인만의 엉뚱발랄한 컴퓨터강의:계산이론
- 로봇의 구조
- AVR ATmega128을 이용한 LED실험 해석 (avr atmega128,led실험,led점멸,led 시프트,쉬프트,pw...
- 2015년 1학기 C프로그래밍 기말시험 핵심체크
소개글