在 Lex 中检查有效的算术表达式(在 C 中)
Checking Valid Arithmetic Expression in Lex (in C)
我必须在 lex 中编写代码来检查算术表达式是否有效。我知道我可以使用 yacc 很容易地做到这一点,但只在 lex 中做并不是那么容易。
我写了下面的代码,但由于某种原因不起作用。
除此之外,我也不知道如何处理二元运算符。
我的错误代码:
%{
#include <stdio.h>
/* Will be using stack to check the validity of arithetic expressions */
char stack[100];
int top = 0;
int validity =0;S
%}
operand [a-zA-Z0-9_]+
%%
/* Will consider unary operators (++,--), binary operators(+,-,*,/,^), braces((,)) and assignment operators (=,+=,-=,*=,^=) */
"(" { stack[top++]='(';}
")" { if(stack[top]!=')') yerror(); else top--;}
[+|"-"|*|/|^|%] { if(stack[top]!='$') yerror(); else stack[top]=='&';}
"++" { if(stack[top]!='$') yerror(); else top--;}
[+"-"*^%]?= { if(top) yerror();}
operand { if(stack[top]=='&') top--; else stack[top++]='$';}
%%
int yerror()
{
printf("Invalid Arithmetic Expression\n");
}
首先,了解如何在 Flex 中编写正则表达式。 (Patterns, Flex manual).
字符class([
…]
)内,引号、星号和竖线都不是特殊的。要包含 - 或 ],您可以使用 \ 转义它们或将它们放在列表的开头,或者在 - 的情况下在结尾。
所以在:
[+|"-"|*|/|^|%]
| 只是列表中的另一个字符,包含它五次不会改变任何内容。 "-"
是一个仅由字符 " 组成的字符范围,尽管我想本意是包括 -。可能你想要[-+*/^%]
或 [+\-*/^%]
.
flex 扫描器无法猜测 +(例如)是一元运算符而不是二元运算符,并将它两次放入列表中规则不会做任何事情;第一条规则将始终生效。
最后,如果您在模式中使用定义(如 operand
),则必须将它们括在大括号中:{operand}
;否则,flex 会将其解释为一个简单的关键字。
以及赋值本身的提示:有效的未加括号的算术表达式可以简化为正则表达式:
term {prefix-operator}*{operand}{postfix-operator}*
expr {term}({infix-operator}{term})*
但是您不能直接使用它,因为 (a) 它不处理括号,(b) 您可能需要允许空格,并且 (c) 它没有正确拒绝 a+++++b
因为 C 坚持词法扫描的 "maximal munch" 规则,所以这与正确的表达式 a++ + ++b
.
不同
但是,您可以将上述正则表达式转换为非常简单的两态状态机。
我必须在 lex 中编写代码来检查算术表达式是否有效。我知道我可以使用 yacc 很容易地做到这一点,但只在 lex 中做并不是那么容易。
我写了下面的代码,但由于某种原因不起作用。 除此之外,我也不知道如何处理二元运算符。
我的错误代码:
%{
#include <stdio.h>
/* Will be using stack to check the validity of arithetic expressions */
char stack[100];
int top = 0;
int validity =0;S
%}
operand [a-zA-Z0-9_]+
%%
/* Will consider unary operators (++,--), binary operators(+,-,*,/,^), braces((,)) and assignment operators (=,+=,-=,*=,^=) */
"(" { stack[top++]='(';}
")" { if(stack[top]!=')') yerror(); else top--;}
[+|"-"|*|/|^|%] { if(stack[top]!='$') yerror(); else stack[top]=='&';}
"++" { if(stack[top]!='$') yerror(); else top--;}
[+"-"*^%]?= { if(top) yerror();}
operand { if(stack[top]=='&') top--; else stack[top++]='$';}
%%
int yerror()
{
printf("Invalid Arithmetic Expression\n");
}
首先,了解如何在 Flex 中编写正则表达式。 (Patterns, Flex manual).
字符class([
…]
)内,引号、星号和竖线都不是特殊的。要包含 - 或 ],您可以使用 \ 转义它们或将它们放在列表的开头,或者在 - 的情况下在结尾。
所以在:
[+|"-"|*|/|^|%]
| 只是列表中的另一个字符,包含它五次不会改变任何内容。 "-"
是一个仅由字符 " 组成的字符范围,尽管我想本意是包括 -。可能你想要[-+*/^%]
或 [+\-*/^%]
.
flex 扫描器无法猜测 +(例如)是一元运算符而不是二元运算符,并将它两次放入列表中规则不会做任何事情;第一条规则将始终生效。
最后,如果您在模式中使用定义(如 operand
),则必须将它们括在大括号中:{operand}
;否则,flex 会将其解释为一个简单的关键字。
以及赋值本身的提示:有效的未加括号的算术表达式可以简化为正则表达式:
term {prefix-operator}*{operand}{postfix-operator}*
expr {term}({infix-operator}{term})*
但是您不能直接使用它,因为 (a) 它不处理括号,(b) 您可能需要允许空格,并且 (c) 它没有正确拒绝 a+++++b
因为 C 坚持词法扫描的 "maximal munch" 规则,所以这与正确的表达式 a++ + ++b
.
但是,您可以将上述正则表达式转换为非常简单的两态状态机。