So *_*ins 3 compiler-construction yacc bison semantic-analysis
我一直在尝试到处寻找示例,但是却徒劳无功。
我正在尝试编写基本的Ruby解释器。为此,我编写了一个弹性词法文件,其中包含标记识别语句和一个语法文件。
我希望我的语法包含语义类型检查。
我的语法文件包含例如:
arg : arg '+' arg
Run Code Online (Sandbox Code Playgroud)
这应该是整数和浮点数的有效规则。
根据阅读的内容,我可以为arg等非终端指定类型,如下所示:
%type <intval> arg
Run Code Online (Sandbox Code Playgroud)
其中“ intval”在联合类型中,并且与int C类型相对应。
但这仅适用于整数,我不确定如何使该规则对浮点数有效。我考虑过要制定两个不同的规则,一个用于整数,一个用于浮点数,例如:
argint : argint '+' argint
argfloat : argfloat '+' argfloat
Run Code Online (Sandbox Code Playgroud)
但是我敢肯定,这样做的方法要好得多,因为这种拙劣的行为要求我制定规则,允许在浮点数和整数之间进行加法运算。
我发现的所有示例都只有一种类型(在类似计算器的示例中通常为整数)。
如何实现指定诸如加法之类的规则可以将int和float用作参数的方法?
非常感谢你。
这不是您想要的答案。我认为您没有看到想要的示例的原因是,在语法文件(.y)中强制执行键入规则是不切实际的。而是,开发人员通过程序.c或.cpp代码完成此操作。通常,无论如何,您都会对已解析的输入进行一些分析,因此,在执行语义规则时,这是副产品。
顺便说一句,鉴于您在问题中重现的语法片段,我不太了解您如何解析表达式。
这就是为什么我声称这是不切实际的。(1)您的类型信息必须渗透到整个语法的非末尾。(2)更糟的是,它必须反映在变量名中。
考虑这个玩具示例,该示例分析可使用标识符,数字常量和四个桌面计算器运算符的简单赋值语句。NUMBER令牌可以是整数(例如42)或浮点数(例如3.14)。假设IDENTIFIER是一个字母AZ。
%token IDENTIFIER NUMBER
%%
stmt : IDENTIFIER '=' expr
;
expr : expr '+' term
| expr '-' term
| term
;
term : term '*' factor
| term '/' factor
| factor
;
factor : '(' expr ')'
| '-' factor
| NUMBER
| IDENTIFIER
;
Run Code Online (Sandbox Code Playgroud)
现在,让我们尝试介绍输入规则。我们将NUMBER令牌分为FLT_NUMBER和INT_NUMBER。我们的expr,term和factor非终端也分为两个:
%token IDENTIFIER FLT_NUMBER INT_NUMBER
stmt : IDENTIFIER '=' int_expr
| IDENTIFIER '=' flt_expr
;
int_expr : int_expr '+' int_term
| int_expr '-' int_term
| int_term
;
flt_expr : flt_expr '+' flt_term
| flt_expr '-' flt_term
| flt_term
;
int_term : int_term '*' int_factor
| int_term '/' int_factor
| int_factor
;
flt_term : flt_term '*' flt_factor
| flt_term '/' flt_factor
| flt_factor
;
int_factor : '(' int_expr ')'
| '-' int_factor
| INT_NUMBER
| int_identifier
;
flt_factor : '(' flt_expr ')'
| '-' flt_factor
| FLT_NUMBER
| flt_identifier
;
int_identifier : IDENTIFIER ;
flt_identifier : IDENTIFIER ;
Run Code Online (Sandbox Code Playgroud)
就目前的语法而言,这是有冲突的:解析器无法判断是将IDENTIFIER识别为a int_identifier还是a flt_identifier。因此,它不知道是否减少A = Bas IDENTIFIER = int_expr或IDENTIFIER = flt_expr。
(在这里,我对Ruby的理解有些柔和:) Ruby(像大多数语言一样)在词法级别上没有提供一种确定标识符的数字类型的方法。将其与老式BASIC进行对比,其中A表示数字,A $表示字符串。换句话说,如果您发明了一种语言,例如,A#表示整数,而A @表示浮点数,则可以完成此工作。
如果您想允许有限的混合类型表达式(例如)int_term '*' flt_factor,则语法会变得更加复杂。
可能存在解决这些问题的方法。使用yacc / bison以外的技术构建的解析器可能会更容易。至少,也许我的草图可以为您提供一些进一步的想法。
| 归档时间: |
|
| 查看次数: |
4531 次 |
| 最近记录: |