Document directory
- (1) grammar analysis
- Running result
Back to document homepage (1) Introduction
Download the code: git clone git: // git.code.sf.net/p/redy/code redy-code
The content of this chapter:
Use YACC to implement a simple arithmetic Calculator
(2) arithmetic Calculator
In this chapter, I will explain how to use YACC to complete a simple four-timer. The calculator functions include:
- There are 26 registers, which are represented by 'A'-'Z' respectively. They are used to save the data for later use.
- Supports addition, subtraction, multiplication, and Division operations.
- Brackets
- If the operation does not support floating-point numbers and the division result is not an integer, the fractional part is discarded.
- When the input is an error expression, the output is "syntax error". Otherwise, the output result is calculated.
Usage:
- Letter = expression indicates saving the expression value in the register. For example, a = 1 + 3. After running, the value of register a is 4.
- The operation unit can be an integer or a register, for example, 1*3 + 2, A + B + 3 * C.
(1) grammar analysis
The priority of the arithmetic operators is:
- Parentheses, arithmetic unit (integer, register)
- Unary operator '-', indicating a negative number
- Multiplication and division Operators
- Plus and minus signs
- Equal sign, used to save the result to the Register
Before writing grammar, we will first introduce the YACC writing format.
- Symbol ': 'The left side is the left side of the generative formula, and the right side is the generative formula. Multiple syntactic symbols on the right are separated by spaces.
- If the grammar symbols on the Left can be exported to multiple strings, use '|' to separate them.
- On the right of each production formula, you can embed the semantic action in braces. $ indicates the attribute of the Left grammar symbol of the generative formula, and $ I indicates the attribute of the right th grammar of the generative formula.
- If no semantic action is embedded in the program, YACC uses the default semantic action.
The algorithm for writing grammar expressions is that the priority of the First operator is high, and then the first step is to the bottom. parentheses and operators (integers and registers) the first level is the highest, and the syntax is:
primary_expr: '(' expr ')' {$$=$2;}| number| letter {$$=reg[$1];};
Where:
- Indicates the semantic action of the first line. The value of the attribute (expr) of the second grammar symbol is assigned to the syntax symbol primary_expr in the left part of the generative formula.
- The third line of semantic action indicates that the value in the register represented by letter is taken out and assigned to primary_expr.
- The second row uses the default semantic Action $ = $1, indicating that the number value is assigned to primary_expr.
Step 2: Compile the syntax for the second operator of priority:
unary_expr: primary_expr | '-' primary_expr {$$=-$2;} ;
Step 3: Enter the multiplication and division numbers:
mul_expr:unary_expr {$$=$1;}| mul_expr '*' unary_expr {$$=$1*$3;}| mul_expr '/' unary_expr {$$=$1/$3;};
Step 4: add and subtract signs:
add_expr:mul_expr {$$=$1;}| add_expr '+' mul_expr {$$=$1+$3;}| add_expr '-' mul_expr {$$=$1-$3;};
Finally:
assign: letter '=' add_expr {reg[$1]=$3;};
Now I have completed the compilation of arithmetic expressions. Next I will show the entire source program.
%{#include<stdio.h>#include<ctype.h>int reg[26];%}%start list%token digit letter%%list: list start '\n' | list error '\n' | start '\n';start: expr {printf("result: %d\n\n",$1);}| assign;number:number digit {$$=$1*10+$2;} |digit ;primary_expr: '(' expr ')' {$$=$2;}| number| letter {$$=reg[$1];};unary_expr: primary_expr | '-' primary_expr {$$=-$2;} ;mul_expr:unary_expr {$$=$1;}| mul_expr '*' unary_expr {$$=$1*$3;}| mul_expr '/' unary_expr {$$=$1/$3;};add_expr:mul_expr {$$=$1;}| add_expr '+' mul_expr {$$=$1+$3;}| add_expr '-' mul_expr {$$=$1-$3;};assign: letter '=' add_expr {reg[$1]=$3;};expr: add_expr ;%%int yylex(){int ch=' ';while(isspace(ch)&&ch!='\n') ch=fgetc(stdin);if(isdigit(ch)){yylval=ch-'0';return digit;}if(isalpha(ch)){yylval=ch-'a';return letter;}return ch;}int main(){return yyparse();}int yyerror(char* s){fprintf(stderr,"%s\n",s);}
Running result
The code for this chapter can be found in tutorial/syntax/simple_cal
Back to document Homepage