我正在尝试解析ocamlyacc中的语法(几乎与常规yacc相同),它支持没有运算符的函数应用程序(如Ocaml或Haskell),以及二进制和一元运算符的常规分类.我正在使用' - '运算符进行减少/减少冲突,它可以用于减法和否定.这是我正在使用的语法示例:
%token <int> INT
%token <string> ID
%token MINUS
%start expr
%type <expr> expr
%nonassoc INT ID
%left MINUS
%left APPLY
%%
expr: INT
{ ExprInt $1 }
| ID
{ ExprId $1 }
| expr MINUS expr
{ ExprSub($1, $3) }
| MINUS expr
{ ExprNeg $2 }
| expr expr %prec APPLY
{ ExprApply($1, $2) };
Run Code Online (Sandbox Code Playgroud)
问题是,当你得到一个像"a - b"这样的表达式时,解析器不知道这是否应该减少为"a(-b)"(否定b,后跟应用程序)或"a - b"(减法).减法减少是正确的.如何解决有利于该规则的冲突?
如果我忘记在我的任何文件的末尾添加一个空行,我的程序会出现语法错误.问题是我的语法期望换行结束当前行.由于新行不存在,因此bison不会生成语法错误,因为它没有完成规则.
我该如何解决这个问题?当我这样做时,我试图做出<<EOF>>回报MY_EOF但是因为一次可怕的死亡而崩溃了.我猜其默认EOF中的代码我没有打电话.我不知道它们可能是什么功能.使用EOF创建错误symbol EOF is used, but is not defined as a token and has no rules
我将传递给yacc中main的参数存储在一个文件中.现在我希望lex从这个文件而不是终端读取它的输入.我知道我可以将yyin指向一个文件,yyin = fopen("fn","r");但只有当main在lex中时才有用.当我在yacc的main中使用这个yyin声明时,它会显示错误,所以请提出一些建议来克服这个问题.
我正在编写一个解析器来解析类似C语法的语法.
首先,它现在可以解析代码:
a = 1;
b = 2;
Run Code Online (Sandbox Code Playgroud)
现在我想在行尾添加分号可选.
最初的YACC规则是:
stmt: expr ';' { ... }
Run Code Online (Sandbox Code Playgroud)
新行由我自己编写的词法分析器处理(代码简化):
rule(/\r\n|\r|\n/) { increase_lineno(); return :PASS }
Run Code Online (Sandbox Code Playgroud)
指令:此处的PASS相当于在LEX中不返回任何内容,它会删除当前匹配的文本并跳到下一个规则,就像通常使用空格一样.
因此,我不能简单地将我的YACC规则更改为:
stmt: expr end_of_stmt { ... }
;
end_of_stmt: ';'
| '\n'
;
Run Code Online (Sandbox Code Playgroud)
所以我选择相应地通过解析器动态地改变词法分析器的状态.
像这样:
stmt: expr { state = :STATEMENT_END } ';' { ... }
Run Code Online (Sandbox Code Playgroud)
并添加一个lexer规则,可以将新行与新状态匹配:
rule(/\r\n|\r|\n/, :STATEMENT_END) { increase_lineno(); state = nil; return ';' }
Run Code Online (Sandbox Code Playgroud)
这意味着当词法分析器处于以下状态时:STATEMENT_END状态.它将像往常一样首先增加行号,然后将状态设置为初始状态,然后假装自己是分号.
奇怪的是,它实际上不适用于以下代码:
a = 1
b = 2
Run Code Online (Sandbox Code Playgroud)
我调试它并得到它实际上并没有得到';' 正如所期望的那样,在数字1之后扫描换行符,并且状态指定的规则并未真正执行.
并且设置新状态的代码在已经扫描新行并且没有返回任何内容之后执行,这意味着,这些工作按以下顺序完成:
a,=和1b …我有一个描述某种语言的yacc文件,我正在使用IMP(eclipse项目)开发一个编辑器.我使用LPG作为解析器生成器,所以我需要从我的yacc文件中提取BNF规则.我收到的yacc文件包含规则和操作.但是,我想只提取要在LPG中使用的语法描述的规则.一种方法是通过手动提取规则并将其重新格式化为BNF语法(或者可以编写程序将其转换为我想要的方式).我想知道是否有自动执行此操作的方法.我在一些博客中读到野牛可以提供帮助,但我无法找到合适的命令.有谁知道如何处理这个问题.
我不能真正发布我所拥有的yacc文件,因为它是保密的.但我可举个例子如下
argExprList:
assignExp
{
// some rules here
}
| assignExpList ',' assignExp
{
//some other rules here
}
;
Run Code Online (Sandbox Code Playgroud)
我希望它被转换成简单的样子
argExpList ::= assignExp|assignExpList ',' assignExp
Run Code Online (Sandbox Code Playgroud) 因此,似乎Happy是Haskell中yacc的强大替代品.是否有同样强大的词法生成器来替换lex/flex?
我没有收到错误,请你帮帮我,这里是.l和.y文件.谢谢.
%{
#include "ifanw.tab.h"
extern int yylval;
%}
%%
"=" { return EQ; }
"!=" { return NE; }
"<" { return LT; }
"<=" { return LE; }
">" { return GT; }
">=" { return GE; }
"+" { return PLUS; }
"-" { return MINUS; }
"*" { return MULT; }
"/" { return DIVIDE; }
")" { return RPAREN; }
"(" { return LPAREN; }
":=" { return ASSIGN; }
";" { return SEMICOLON; }
"IF" …Run Code Online (Sandbox Code Playgroud) 我正在学习F#,因为我想写一个词法分析器和解析器.我对这种处理有一点经验,但确实需要正确地学习它和F#.
在学习F#的lexing/parsing功能时,学习lex和yacc是否足够?
或者是否存在一些差异,这意味着lex/yacc的代码将无法与fslex和fsyacc一起使用?
我是OCaml新手,我正在尝试编写一个类似OCaml的简单语法,我无法弄清楚这一点.我的语法允许这样的事情:
let sub = fun x -> fun y -> x - y;;
Run Code Online (Sandbox Code Playgroud)
但是,如果我想使用如此定义的函数,我可以写:(sub 7) 3但是我不能写sub 7 3,这真的让我烦恼.由于某种原因,它被解释为好像我写的sub (7 3)(将其视为7带参数的函数3).相关部分是:
/* other operators, then at the very end: */
%left APPLY
/* ... */
expr:
/* ... */
| expr expr %prec APPLY { Apply($1, $2) }
Run Code Online (Sandbox Code Playgroud)
谢谢!