|
|
(One intermediate revision by the same user not shown) |
Line 1: |
Line 1: |
| {{TOCright}}
| | #REDIRECT [[ist:The YACC Parser Generator/Exercise 5]] |
| == Problema ==
| |
| | |
| O problema a resolver consiste na localização na pilha dos argumentos actuais de uma função C++. Considere que os argumentos apenas podem ser dos tipos '''char''', '''short''', '''int''', ponteiro, '''float''' e '''double''' (ocupando, respectivamente, 1, 2, 4, 4, 4 e 8 bytes). Considere ainda que o argumento mais à esquerda está na posição 8.
| |
| | |
| Construa um ficheiro YACC (.y) que receba uma assinatura de uma função e que imprima a posição de cada argumento. Considere que a especificação Flex (não é necessário implementá-la) detecta os seguintes tokens: '''tVOID''', '''tID''', '''tCHAR''', '''tSHORT''', '''tINT''', '''tFLOAT''', '''tDOUBLE''', '''(''', ''')''', ''',''', '''*''' e ''';'''.
| |
| | |
| Por exemplo, na seguinte assinatura, os argumentos estarão (respectivamente), nas posições 8, 12, 16 e 17:
| |
| <cpp>
| |
| void f(int a, char *b, char c, double d);
| |
| </cpp>
| |
| == The Lexical Analyzer (Flex) Specification ==
| |
| | |
| The lexical analyzer ('''funcoffs.l''') is very simple and limited to recognizing the indispensable tokens.
| |
| <text>
| |
| %option 8bit noyywrap yylineno
| |
| %{
| |
| #include <string>
| |
| #include "y.tab.h" | |
| %}
| |
| %%
| |
| | |
| "void" return tVOID;
| |
| "char" return tCHAR;
| |
| "short" return tSHORT;
| |
| "int" return tINT;
| |
| "float" return tFLOAT;
| |
| "double" return tDOUBLE;
| |
| | |
| [_A-Za-z][_A-Za-z0-9]* yylval.s = new std::string(yytext); return tID;
| |
| [,()*;] return *yytext; | |
| | |
| .|\n ; // ignore the rest
| |
| | |
| %%
| |
| </text>
| |
| | |
| == The Syntactic Analyzer (YACC) Specification ==
| |
| | |
| The syntactic analyzer ('''funcoffs.y''') will be built to immediately compute the expressions in a syntax-directed fashion as they occur. It is, thus, important to use trees that build nodes as the expressions occur (left-recursive grammars).
| |
| <text>
| |
| %{
| |
| #include <string>
| |
| #include <iostream>
| |
| inline void yyerror(const char *msg) { std::cerr << msg << std::endl; }
| |
| %}
| |
| %union {
| |
| int i;
| |
| std::string *s;
| |
| std::pair<int, std::string> *p;
| |
| }
| |
| | |
| %token <s> tID
| |
| %token tVOID tCHAR tSHORT tINT tFLOAT tDOUBLE
| |
| | |
| %type <i> args atype
| |
| %type <p> arg
| |
| | |
| %%
| |
| | |
| funcs: func
| |
| | funcs func
| |
| ;
| |
| | |
| func : rtype tID '(' ')' ';'
| |
| | rtype tID '(' args ')' ';'
| |
| ;
| |
| | |
| args : arg { std::cout << $1->second << "@" << ($$ = 8) << std::endl; $$ += $1->first; delete $1; }
| |
| | args ',' arg { std::cout << $3->second << "@" << ($$ = $1) << std::endl; $$ += $3->first; delete $3; }
| |
| ;
| |
| | |
| arg : atype tID { $$ = new std::pair<int,std::string>($1,*$2); delete $2; }
| |
| ;
| |
| | |
| rtype : tVOID | tCHAR | tSHORT | tINT | tFLOAT | tDOUBLE | rtype '*' ;
| |
| | |
| atype : tCHAR { $$ = 1; }
| |
| | tSHORT { $$ = 2; }
| |
| | tINT { $$ = 4; }
| |
| | tFLOAT { $$ = 4; }
| |
| | tDOUBLE { $$ = 8; }
| |
| | atype '*' { $$ = 4; }
| |
| ;
| |
| | |
| %%
| |
| extern int yylex();
| |
| extern int yyparse();
| |
| int main() {
| |
| return yyparse();
| |
| }
| |
| </text>
| |
| | |
| == How to Compile? ==
| |
| | |
| The Flex specification is processed as follows (the file '''lex.yy.c''' is produced):
| |
| | |
| flex funcoffs.l
| |
| | |
| The YACC specification is processed as follows (files '''y.tab.h''', needed by the Flex-generated code, and '''y.tab.c'''): | |
| | |
| byacc -dtv funcoffs.y
| |
| | |
| Compiling the C/C++ code (it is C++ simply because we programmed the extra code in that language):
| |
| | |
| g++ -c lex.yy.c
| |
| g++ -c y.tab.c
| |
| g++ -o funcoffs y.tab.o lex.yy.o
| |
| | |
| [[category:Compiladores]]
| |
| [[category:Ensino]]
| |