CPW Part 16 (A): Equality and Relational Expressions in the Grammar
The new operators "==“, ”!=“, ”>“, ”>=“, ”<“ and ”<=" should habe the same meaning, associativity and precedence as in C (See Session 8, Page 4). Below the corresponding grammar. Note that some of the production rules were simply renamed (e.g. expr into additive-expr and term into multiplicative-expr). But essentially just two new production rules, i.e. equality-expr and relational-expr, were added.
\[\begin{array}{rcl}\text{input-sequence} & = & \{\; $> \; \text{assignment-expr}\; \texttt{;}\; |\; $< \; \text{assignment-expr}\; \texttt{;}\; |\; \text{expr-statement}\; \}\; \\\text{expr-statement} & = & \text{assignment-expr}\; \texttt{;}\; \\\text{assignment-expr} & = & \text{equality-expr}\; [\; \texttt{=}\; \text{assignment-expr}\; ]\; \\\text{equality-expr} & = & \text{relational-expr}\; \{\; (\; \texttt{"=="}\; |\; \texttt{"!="}\; )\; \text{relational-expr} \} \\\text{relational-expr} & = & \text{additive-expr}\; \{\; (\; \texttt{">"}\; |\; \texttt{"<"}\; |\; \texttt{">="}\; |\; \texttt{"<="}\; )\; \text{additive-expr} \} \\\text{additive-expr} & = & \text{multiplicative-expr}\; \{\; (\; \texttt{"+"}\; |\; \texttt{"-"}\; )\; \text{multiplicative-expr} \} \\\text{multiplicative-expr} & = & \text{unary-expr}\; \{\; (\; \texttt{"*"}\; |\; \texttt{"/"}\; |\; \texttt{"%"} )\; \text{unary-expr} \} \\\text{unary-expr} & = & \text{primary-expr}\; |\; (\; \texttt{"+"}\; |\; \texttt{"-"}\;)\; \text{unary-expr} \\\text{primary-expr} & = & \text{identifier}\; \\ & | & \text{dec-literal}\; \\ & | & \text{hex-literal}\; \\ & | & \text{oct-literal}\; \\ & | & \texttt{"("}\; \text{assignment-expr}\; \texttt{")"}\; \\\end{array}\]Exercise
In enum ExprKind add constants for the new binary operators:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | enum ExprKind
{
EK_BINARY,
// binary expression
EK_ADD = EK_BINARY,
EK_ASSIGN,
EK_EQUAL,
EK_NOT_EQUAL,
EK_GREATER,
EK_GREATER_EQUAL,
EK_LESS,
EK_LESS_EQUAL,
EK_SUB,
EK_MUL,
EK_DIV,
EK_MOD,
EK_BINARY_END,
// ...
};
|
Update the parser for the new grammar:
-
Rename parse functions to reflect the naming used in the grammar. E.g rename parseExpr() into parseAdditiveExpr(), etc. This is annoying but when a project grows such modifications are part of the game.
-
Add parse the functions parseEqualityExpr() and parseRelationalExpr() for the corresponding production rules.
What Should Work Now
After this update make sure that you can build xtest_abc:
theon$ make gcc -o xgen_tokenkind xgen_tokenkind.c -lm ./xgen_tokenkind tokenkind.txt gen_tokenkind.h gen_strtokenkind.c gcc -c -Wall -Wcast-qual -MT xtest_abc.o -MMD -MP -MF xtest_abc.c.d xtest_abc.c gcc -c -Wall -Wcast-qual -MT expr.o -MMD -MP -MF expr.c.d expr.c gcc -c -Wall -Wcast-qual -MT finalize.o -MMD -MP -MF finalize.c.d finalize.c gcc -c -Wall -Wcast-qual -MT gen.o -MMD -MP -MF gen.c.d gen.c gcc -c -Wall -Wcast-qual -MT lexer.o -MMD -MP -MF lexer.c.d lexer.c gcc -c -Wall -Wcast-qual -MT memregion.o -MMD -MP -MF memregion.c.d memregion.c gcc -c -Wall -Wcast-qual -MT parser.o -MMD -MP -MF parser.c.d parser.c gcc -c -Wall -Wcast-qual -MT str.o -MMD -MP -MF str.c.d str.c gcc -c -Wall -Wcast-qual -MT sym.o -MMD -MP -MF sym.c.d sym.c gcc -c -Wall -Wcast-qual -MT tokenkind.o -MMD -MP -MF tokenkind.c.d tokenkind.c gcc -c -Wall -Wcast-qual -MT ustr.o -MMD -MP -MF ustr.c.d ustr.c gcc -o xtest_abc xtest_abc.o expr.o finalize.o gen.o lexer.o memregion.o parser.o str.o sym.o tokenkind.o ustr.o -lm gcc -c -Wall -Wcast-qual -MT xtest_cond.o -MMD -MP -MF xtest_cond.c.d xtest_cond.c gcc -o xtest_cond xtest_cond.o expr.o finalize.o gen.o lexer.o memregion.o parser.o str.o sym.o tokenkind.o ustr.o -lm gcc -c -Wall -Wcast-qual -MT xtest_expr.o -MMD -MP -MF xtest_expr.c.d xtest_expr.c gcc -o xtest_expr xtest_expr.o expr.o finalize.o gen.o lexer.o memregion.o parser.o str.o sym.o tokenkind.o ustr.o -lm gcc -c -Wall -Wcast-qual -MT xtest_finalize.o -MMD -MP -MF xtest_finalize.c.d xtest_finalize.c gcc -o xtest_finalize xtest_finalize.o expr.o finalize.o gen.o lexer.o memregion.o parser.o str.o sym.o tokenkind.o ustr.o -lm gcc -c -Wall -Wcast-qual -MT xtest_gen.o -MMD -MP -MF xtest_gen.c.d xtest_gen.c gcc -o xtest_gen xtest_gen.o expr.o finalize.o gen.o lexer.o memregion.o parser.o str.o sym.o tokenkind.o ustr.o -lm gcc -c -Wall -Wcast-qual -MT xtest_lexer_sanity.o -MMD -MP -MF xtest_lexer_sanity.c.d xtest_lexer_sanity.c gcc -o xtest_lexer_sanity xtest_lexer_sanity.o expr.o finalize.o gen.o lexer.o memregion.o parser.o str.o sym.o tokenkind.o ustr.o -lm gcc -c -Wall -Wcast-qual -MT xtest_lexer.o -MMD -MP -MF xtest_lexer.c.d xtest_lexer.c gcc -o xtest_lexer xtest_lexer.o expr.o finalize.o gen.o lexer.o memregion.o parser.o str.o sym.o tokenkind.o ustr.o -lm gcc -c -Wall -Wcast-qual -MT xtest_memregion.o -MMD -MP -MF xtest_memregion.c.d xtest_memregion.c gcc -o xtest_memregion xtest_memregion.o expr.o finalize.o gen.o lexer.o memregion.o parser.o str.o sym.o tokenkind.o ustr.o -lm gcc -c -Wall -Wcast-qual -MT xtest_sym.o -MMD -MP -MF xtest_sym.c.d xtest_sym.c gcc -o xtest_sym xtest_sym.o expr.o finalize.o gen.o lexer.o memregion.o parser.o str.o sym.o tokenkind.o ustr.o -lm gcc -c -Wall -Wcast-qual -MT xtest_ustr.o -MMD -MP -MF xtest_ustr.c.d xtest_ustr.c gcc -o xtest_ustr xtest_ustr.o expr.o finalize.o gen.o lexer.o memregion.o parser.o str.o sym.o tokenkind.o ustr.o -lm gcc -c -Wall -Wcast-qual -MT xgen_tokenkind.o -MMD -MP -MF xgen_tokenkind.c.d xgen_tokenkind.c theon$
Test the compiler with expressions like in this example (of course you can extend this):
1 2 3 4 5 6 | x == y;
x != y;
x <= y;
x >= y;
x < y;
x > y;
|
If you also want to update const folding use
1 2 3 4 5 6 7 8 9 10 11 12 | x == y;
x != y;
x <= y;
x >= y;
x < y;
x > y;
3 == 4;
3 != 4;
3 <= 4;
3 >= 4;
3 < 4;
3 > 4;
|
Expected Error
You will get an assertion failure from the code generator (i.e. in loadExpr()) but you should not get a syntax error:
theon$ ./xtest_abc < test.abc loadExpr: internal error. kind = 2 warning: register 6 not released ldzwq 0x0, %2 theon$
So in the next step you should
-
adapt the implementation of loadExpr().
-
handle in printExprNode() the new expression kinds.
-
handle in constFoldBinary() the new expression kinds (optional).