lemon之Hello World(续3)
来源:互联网 发布:suse linux双网卡绑定 编辑:程序博客网 时间:2024/06/04 01:37
之前几篇短文的主函数都是写死了代码,没有用户交互过程。现在,咱们利用flex和lemon结合,
制作一个简单的计算器。之所以说简单,是因为只含有+-*/四个运算,并且还不支持括号。
相关文件如下:
1、数据结构exampleDef.h
#ifndef __EXAMPLE_DEF_H__
#define __EXAMPLE_DEF_H__
//lemon token struct
struct Token {
double value;
unsigned n;
};
//flex
typedef union {
double dval;
struct symtab *symp;
} yystype;
# define YYSTYPE yystype
# define YYSTYPE_IS_TRIVIAL 1
/* extern YYSTYPE yylval; */
YYSTYPE yylval;
#endif
2、lemon语法规则文件example.y
%include {
#include <iostream>
#include "example.h"
#include "exampleDef.h"
/*
void destructor(Token t) {
std::cout << "destructor.value=" << t.value << std::endl;
std::cout << "destructor.n=" << t.n << std::endl;
}
*/
}
%token_prefix TOKEN_
%token_type {Token}
// %token_destructor {destructor($$);}
%type expr {Token}
%type NUM {Token}
%left PLUS MINUS.
%left DIVIDE TIMES.
%syntax_error {
std::cout << "Syntax error!" << std::endl;
}
main ::= in.
in ::= .
in ::= in program NEWLINE.
program ::= expr(A). {
std::cout << "Result=" << A.value << std::endl;
// std::cout << "Result.n=" << A.n << std::endl;
}
expr(A) ::= expr(B) MINUS expr(C). {
A.value = B.value - C.value ;
A.n = B.n + 1 + C.n + 1;
}
expr(A) ::= expr(B) PLUS expr(C). {
A.value = B.value + C.value ;
A.n = B.n + 1 + C.n + 1;
}
expr(A) ::= expr(B) TIMES expr(C). {
A.value = B.value * C.value ;
A.n = B.n + 1 + C.n + 1;
}
expr(A) ::= expr(B) DIVIDE expr(C). {
if(C.value != 0){
A.value = B.value / C.value ;
A.n = B.n + 1 + C.n + 1;
}else{
std::cout << "divide by zero" << std::endl;
}
} /* end of DIVIDE */
expr(A) ::= NUM(B). {
A.value = B.value;
A.n = B.n + 1;
}
3、lex词法规则文件lexer.l
%{
#include "exampleDef.h"
#include "example.h"
#include <string.h>
#include <math.h>
int parserline = 1;
int parsercol = 1;
%}
%%
[0-9]+|[0-9]*/.[0-9]+ { /* float decimal */
parsercol += (int) strlen(yytext);
yylval.dval = atof(yytext);
return TOKEN_NUM;
}
[ /t] { /* ignore but count white space */
parsercol += (int) strlen(yytext);
}
[A-Za-z][A-Za-z0-9]* { /* ignore but needed for variables */
return 0;
}
"+" { return TOKEN_PLUS; }
"-" { return TOKEN_MINUS; }
"*" { return TOKEN_TIMES; }
"/" { return TOKEN_DIVIDE; }
/n {
parsercol = 0;
++parserline;
return TOKEN_NEWLINE;
}
. {
parsercol += (int) strlen(yytext);
return yytext[0];
}
%%
/**
* reset the parserline and column count
*
*
*/
void reset_lexer(void)
{
parserline = 1;
parsercol = 1;
}
/**
* yyerror() is invoked when the lexer or the parser encounter
* an error. The error message is passed via *s
*
*
*/
void yyerror(char *s)
{
printf("error: %s at parserline: %d parsercol: %d/n",s,parserline,parsercol);
}
int yywrap(void)
{
return 1;
}
4、头文件封装LAPI.h
#ifndef __LAPI_H__
#define __LAPI_H__
#include "example.c"
/**
* We have to declare these here - they're not in any header files
* we can inclde. yyparse() is declared with an empty argument list
* so that it is compatible with the generated C code from bison.
*
*/
extern FILE *yyin;
typedef struct yy_buffer_state *YY_BUFFER_STATE;
extern "C" {
int yylex( void );
YY_BUFFER_STATE yy_scan_string( const char * );
void yy_delete_buffer( YY_BUFFER_STATE );
}
#endif
5、主函数main.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#define BUFS 1024
#include "LAPI.h"
int main(int argc,char** argv)
{
int n;
int yv;
char buf[BUFS+1];
void* pParser = ParseAlloc (malloc);
struct Token t0,t1;
struct Token mToken;
t0.n=0;
t0.value=0;
std::cout << "Enter an expression like 3+5 <return>" << std::endl;
std::cout << " Terminate with ^D" << std::endl;
while ( ( n=read(fileno(stdin), buf, BUFS )) > 0)
{
buf[n]='/0';
yy_scan_string(buf);
// on EOF yylex will return 0
while( (yv=yylex()) != 0)
{
// std::cout << " yylex() " << yv << " yylval.dval " << yylval.dval << std::endl;
t0.value=yylval.dval;
Parse (pParser, yv, t0);
}
}
Parse (pParser, 0, t0);
ParseFree(pParser, free );
}
6、Makefile
# Compiler flags
CFLAGS = -Wall -W -O2 -s -pipe
CLMFLAGS = -Wall -W -O2 -s -pipe -lm
LFLAGS = -O2 -s -pipe
calc: main.c lex
g++ -o calc -s -pipe main.c lexer.o -lm
lex: lexer.l example
flex lexer.l
test -e lex.yy.c && mv lex.yy.c lexer.c
gcc -o lexer.o -c lexer.c
example: example.y
lemon example.y
- lemon之Hello World(续3)
- lemon之Hello World(续1)
- lemon之Hello World(续2)
- lemon之Hello World(续4)
- lemon之Hello World
- Qt学习之路(3):Hello, world!(续)
- Qt学习之路(3):Hello, world!(续)
- Qt学习之路(3):Hello, world!(续)
- Qt学习之路(3):Hello, world!(续)
- Qt学习之路(3):Hello, world!(续)
- Qt学习之路(3):Hello, world!(续)
- Qt学习之路(3):Hello, world!(续)
- Qt学习之路(3):Hello, world!(续)
- Qt 学习之路 2(3):Hello, world!
- Qt 学习之路 2(3):Hello, world! 笔记
- Qt 学习之路 2(3):Hello, world!
- Velocity之Hello World(入门实例)
- JavaBean 之Hello World(入门实例)
- JMS介绍:我对JMS的理解和认识
- 8数码 BFS
- 修改Andriod模拟器的分辨率
- ORA-12154
- 入世十年我国计算机及相关服务业的发展报告-3
- lemon之Hello World(续3)
- Delphi流的操作
- error LNK2001: unresolved external symbol "char * __stdcall _com_util::ConvertBSTRToString(wchar_t *
- 入世十年我国计算机及相关服务业的发展报告-4
- 如何让appwidget开机后自动添加到Home Screen上
- 入世十年我国计算机及相关服务业的发展报告-5
- 数组的误用
- Photoshop快捷键
- 8.2.2 命令设计模式