📜  Lex程序实现一个简单的计算器(1)

📅  最后修改于: 2023-12-03 14:43:53.259000             🧑  作者: Mango

用Lex程序实现一个简单的计算器

简介

Lex程序是一种自动化工具,可用于生成基于正则表达式的词法分析器。本文将介绍如何使用Lex程序实现一个简单的计算器,支持基本的四则运算和括号。

实现步骤
步骤1:定义词法分析器

首先,我们需要定义词法分析器,以便能够识别输入的表达式中的单词(例如数字、运算符等)。以下是我们的词法分析器:

%{
#include <stdio.h>
%}

%%

[ \t\n]  ;  // 忽略空格、制表符和换行符

[0-9]+\.[0-9]+|[0-9]+   printf("NUMBER ");
[+\-*/(){}]    printf("%c ", yytext[0]);

.    ;  // 忽略其他字符

%%

int main()
{
    yylex();
    return 0;
}

上述代码定义了一个简单的词法分析器,它可以识别数字和运算符。

步骤2:实现语法分析器

现在,我们需要实现一个语法分析器来解析输入的表达式。语法分析器通常使用递归下降分析法,也就是说,它会从输入的表达式的最外层开始,逐步解析内层的子表达式。以下是我们的语法分析器:

%{
#include <stdio.h>
#include <stdlib.h>
#define YY_DECL int yylex()
int yylex();
void yyerror(char *);

int brace = 0;
%}

%union {
    int num;
    char op;
}

%token NUMBER
%token PLUS MINUS TIMES DIVIDE LPAREN RPAREN LBRACE RBRACE

%left PLUS MINUS
%left TIMES DIVIDE
%left UMINUS

%type <num> expr term factor

%%

input:  /* nothing */  
        | input line ;

line: '\n' { brace = 0; }  
    | expr '\n' { printf("= %d\n", $1); brace = 0; }
    | error '\n' { yyerror("Syntax error"); brace = 0; }

expr: term  
    | expr PLUS term  { $$ = $1 + $3; }
    | expr MINUS term { $$ = $1 - $3; }

term: factor        
    | term TIMES factor   { $$ = $1 * $3; }
    | term DIVIDE factor  { if ($3 == 0) yyerror("Divide by zero"); else $$ = $1 / $3; }

factor: NUMBER         
    | LPAREN expr RPAREN  { $$ = $2; }
    | MINUS factor %prec UMINUS { $$ = -$2; }

%%

int main()
{
    yyparse();
    return 0;
}

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

上述代码实现了一个简单的语法分析器,它可以识别四则运算和括号。

步骤3:编译并运行程序

现在,我们可以将上面两个步骤中的代码片段合并到一个文件中,并使用下面的命令将其编译:

$ lex calculator.l
$ gcc lex.yy.c -o calculator -ll

接下来,我们可以运行程序:

$ ./calculator
1+2*3
= 7

(1+2)*3
= 9

-1+(1+2)*-3
= -8
总结

本文介绍了如何使用Lex程序实现一个简单的计算器。通过词法分析器和语法分析器的组合,我们可以解析输入的表达式并计算其值。这里只是一个简单的例子,但是它可以作为您自己的项目的起点。