Skip to content

Commit 88a21fc

Browse files
Create README.md
1 parent 8a7bd77 commit 88a21fc

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Lex and Yacc: Simple Calculator Example
2+
3+
## Introduction
4+
Lex and Yacc are powerful tools used to generate lexical analyzers (scanners) and parsers. In this guide, we will create a simple calculator using Lex (Flex) and Yacc (Bison) that can evaluate expressions with addition, subtraction, multiplication, and variable assignment.
5+
6+
## Prerequisites
7+
Ensure you have `flex` and `bison` installed:
8+
9+
### On Linux/macOS:
10+
```sh
11+
sudo apt install flex bison # Ubuntu/Debian
12+
sudo pacman -S flex bison # Arch Linux
13+
brew install flex bison # macOS (Homebrew)
14+
```
15+
16+
### On Windows:
17+
Use MinGW or Cygwin to install `flex` and `bison`.
18+
19+
## Understanding Lex and Yacc Internal Functions
20+
Lex and Yacc use several internal functions that play key roles in lexical analysis and parsing:
21+
22+
- **`yyparse()`**: This function is automatically generated by Yacc (Bison). It drives the parsing process by calling `yylex()` to fetch tokens and applying grammar rules.
23+
- **`yylex()`**: This function is generated by Lex (Flex). It scans the input text and returns tokens to the parser. It is responsible for pattern matching based on the rules defined in the `.l` file.
24+
- **`yyerror(const char *s)`**: This function is called by `yyparse()` whenever a syntax error occurs. It prints an error message, allowing debugging of incorrect input.
25+
26+
## Writing the Lex Scanner
27+
Create a file named `scanner.l` with the following content:
28+
29+
```c
30+
%{
31+
#include "y.tab.h"
32+
#include <stdlib.h>
33+
extern int yylval;
34+
%}
35+
36+
%option noyywrap
37+
38+
%%
39+
[0-9]+ { yylval = atoi(yytext); return NUMBER; }
40+
[a-z] { yylval = yytext[0]; return NAME; }
41+
[ \t] ; /* Ignore whitespace */
42+
\n return 0; /* Logical EOF */
43+
. return yytext[0];
44+
%%
45+
```
46+
47+
## Writing the Yacc Parser
48+
Create a file named `parser.y`:
49+
50+
```c
51+
%{
52+
#include <stdio.h>
53+
int yylex();
54+
void yyerror (char const *s) {
55+
fprintf (stderr, "%s\n", s);
56+
}
57+
%}
58+
59+
%token NAME NUMBER
60+
61+
%%
62+
63+
statement: NAME '=' expression { printf("%c = %d\n", $1, $3); }
64+
| expression { printf("= %d\n", $1); }
65+
;
66+
67+
expression: expression '+' NUMBER { $$ = $1 + $3; }
68+
| expression '-' NUMBER { $$ = $1 - $3; }
69+
| expression '*' NUMBER { $$ = $1 * $3; }
70+
| '(' expression ')' { $$ = $2; }
71+
| NUMBER { $$ = $1; }
72+
;
73+
74+
%%
75+
76+
int main() {
77+
yyparse();
78+
return 0;
79+
}
80+
```
81+
82+
## Compiling and Running the Calculator
83+
Run the following commands:
84+
85+
```sh
86+
flex scanner.l
87+
bison -d parser.y
88+
gcc lex.yy.c parser.tab.c -o calculator -lm
89+
./calculator
90+
```
91+
92+
### Example Input/Output:
93+
```
94+
x = 3 + 5
95+
x = 8
96+
5 * 2
97+
= 10
98+
```
99+
100+
## Extending the Calculator
101+
- Add division (`/` operator)
102+
- Implement variable storage
103+
- Support floating-point numbers
104+
105+
This guide provides a basic starting point for learning Lex and Yacc. Experiment and extend it to build more complex parsers!
106+

0 commit comments

Comments
 (0)