.NET有一个很好的yacc/bison类型LALR解析器生成器吗?
我想在yacc的main函数中解析我给解析器的字符串.我知道这可以通过使用来完成,yy_scan_string但我不知道如何使用它.我搜索了网页和手册页,但我仍然不清楚.请帮我.
我希望能够使用flex/bison解析规则解析非空的,一个或多个元素,逗号分隔(以及可选的带括号的)列表.
一些例如可解析的列表:
等等
我使用以下规则来解析列表(最终结果是解析元素'顶级列表'),但它们在解析时似乎没有给出所需的结果(在提供有效列表时我得到语法错误).关于我如何设置它的任何建议?
cList : ELEMENT
{
...
}
| cList COMMA ELEMENT
{
...
}
;
topLevelList : LPAREN cList RPAREN
{
...
}
| cList
{
...
}
;
Run Code Online (Sandbox Code Playgroud) 我正在研究一个简单的SQL选择,如查询解析器,我需要能够捕获可以在某些地方字面上出现的子查询.我发现lexer状态是最好的解决方案,并且能够使用花括号来标记开始和结束.但是,子查询将用括号分隔,而不是用卷曲分隔,括号也可以在其他地方出现,所以我不能成为每个开放状态的状态.解析器随时可以使用此信息,因此我希望在解析器规则中的适当位置调用begin和end.然而这并不起作用,因为词法分析器似乎一次性标记了流,因此令牌在INITIAL状态下生成.这个问题有解决方法吗?以下是我尝试做的概述:
def p_value_subquery(p):
"""
value : start_sub end_sub
"""
p[0] = "( " + p[1] + " )"
def p_start_sub(p):
"""
start_sub : OPAR
"""
start_subquery(p.lexer)
p[0] = p[1]
def p_end_sub(p):
"""
end_sub : CPAR
"""
subquery = end_subquery(p.lexer)
p[0] = subquery
Run Code Online (Sandbox Code Playgroud)
start_subquery()和end_subquery()定义如下:
def start_subquery(lexer):
lexer.code_start = lexer.lexpos # Record the starting position
lexer.level = 1
lexer.begin('subquery')
def end_subquery(lexer):
value = lexer.lexdata[lexer.code_start:lexer.lexpos-1]
lexer.lineno += value.count('\n')
lexer.begin('INITIAL')
return value
Run Code Online (Sandbox Code Playgroud)
词法分析器令牌只是用于检测近距离:
@lex.TOKEN(r"\(")
def t_subquery_SUBQST(t):
lexer.level += 1
@lex.TOKEN(r"\)")
def t_subquery_SUBQEN(t):
lexer.level -= …Run Code Online (Sandbox Code Playgroud) {%
#include<stdio.h>
#include<stdlib.h>
%}
%token ID NUM IF THEN LE GE EQ NE OR AND ELSE
%right '='
%left AND OR
%left '<' '>' LE GE EQ NE
%left '+''-'
%left '*''/'
%right UMINUS
%left '!'
%%
Run Code Online (Sandbox Code Playgroud)
提到上面是yacc程序的一部分,用于简单的IF ELSE程序....我只是一个初学者而且不明白我们的意思%right和%left术语...... plz在这个场合帮助我......
当使用带有空右侧的规则编写("理论")语法时,总是使用诸如ε(或1)之类的符号来使这个空白显式:
A ? ? | a A
Run Code Online (Sandbox Code Playgroud)
Yacc和其他人的这种语法看起来就像
a: | 'a' a
Run Code Online (Sandbox Code Playgroud)
或"更糟"
a: { $$ = new_list(); }
| a 'a' { $$ = $1; $$->append($1); }
;
Run Code Online (Sandbox Code Playgroud)
事实上,在"真实世界语法"(Yacc,Bison等)规则的这个空的右侧部分没有明确标记为空的麻烦我:很容易错过rhs空的事实,或者更糟糕的是:忘记插入|并实际使用中规则操作:
a: { $$ = new_list(); }
a 'a' { $$ = $1; $$->append($1); }
;
Run Code Online (Sandbox Code Playgroud)
1)我不知道有任何工具可以提供显式空rhs的方法.有吗?
Bison的未来版本可能支持专用符号,在非空rhs中使用时会出现错误,而在留下隐式空rhs时会出现警告.
2)人们认为这有用吗?
3)你建议的符号是什么?
目前,候选人是$empty:
a: $empty { $$ = new_list(); }
| a 'a' { $$ = $1; $$->append($1); }
;
Run Code Online (Sandbox Code Playgroud)
选择的语法是%empty:
a: %empty { $$ = …Run Code Online (Sandbox Code Playgroud) 我正在构建一个词法和语法分析器.当我尝试将flex与我的.l文件一起使用时,我收到以下警告.
littleDuck.l:26: warning, rule cannot be matched
Run Code Online (Sandbox Code Playgroud)
规则26是以{cteI}开头的规则,我的规则部分如下:
[ \t\n] ;
{RW} {return RESERVED;}
{id} {return ID;}
{ops} {return OPERATOR;}
{seps} {return SEPARATOR;}
{cteI} {yylval.ival = atoi(yytext); return INT;}
{cteF} {yylval.fval = atof(yytext); return FLOAT;}
{ctestring} {yylval.sval = strdup(yytext); return STRING;}
. ;
Run Code Online (Sandbox Code Playgroud)
另外,我的定义部分是这样的:
RW program|var|int|float|print|else|if
id ([a-z]|[A-Z)([a-z]|[A-Z]|[0-9])*
ops "="|"<"|">"|"<>"|"+"|"-"|"/"|"*"
seps ":"|","|";"|"{"|"}"|"("|")"
cteI [0-9]+
cteF {cteI}(\.{cteI}((e|E)("+"|"-")?{cteI})?)?
ctestring (\".*\")
Run Code Online (Sandbox Code Playgroud)
为什么会出现此警告,如何修改我的文件以使其不显示?
我目前正在尝试使用Flex + Bison编写一个小编译器,但我在错误处理方面有点迷失,特别是如何使所有东西都融合在一起.为了激发讨论,请考虑我用于字符串文字的以下词法分析器片段:
["] { BEGIN(STRING_LITERAL); init_string_buffer(); }
<STRING_LITERAL>{
\\\\ { add_char_to_buffer('\\'); }
\\\" { add_char_to_buffer('\"'); }
\\. { /*Invalid escape. How do I treat this error?*/ }
["] { BEGIN(INITIAL); yylval = get_string_buffer(); return TK_STRING; }
}
Run Code Online (Sandbox Code Playgroud)
如何处理无效转义的情况?现在我只是打印一条错误消息并打电话exit但我更愿意继续前进并在可能的情况下检测每个文件多个错误.
我的问题:
我正在尝试生成一个编译器,所以我可以在之后传递一个.c文件.
我从http://www.quut.com/c/ANSI-C-grammar-y.html下载了YACC和LEX语法,并将它们命名为clexyacc.l和clexyacc.y
在终端上生成它时我做了:
yacc -d clexyacc.y
lex clexyacc.l
Run Code Online (Sandbox Code Playgroud)
一切都很好.当我继续到最后一部分时,我得到了一些错误.
最后一部分是:cc lex.yy.c y.tab.c -oclexyacc.exe
但我得到这些错误:
Run Code Online (Sandbox Code Playgroud)y.tab.c:2261:16: warning: implicit declaration of function 'yylex' is invalid in C99 [-Wimplicit-function-declaration] yychar = YYLEX; ^ y.tab.c:1617:16: note: expanded from macro 'YYLEX' # define YYLEX yylex () ^ y.tab.c:2379:7: warning: implicit declaration of function 'yyerror' is invalid in C99 [-Wimplicit-function-declaration] yyerror (YY_("syntax error")); ^ clexyacc.y:530:6: error: conflicting types for 'yyerror' void yyerror(const char *s) ^ y.tab.c:2379:7: note: previous implicit declaration is here yyerror (YY_("syntax …
我有使用复制字符串lexeme的flex代码strdup().
%{
#include "json.tab.h"
#define YY_DECL extern "C" int yylex()
%}
%option noyywrap
%%
[ \t\n]+ ;
\"[a-zA-Z]+\" {yylval.sval = strdup(yytext); return STRING; }
[0-9]+ {yylval.ival = atoi(yytext); return NUMBER; }
. {return yytext[0];} ;
%%
Run Code Online (Sandbox Code Playgroud)
strdup()分配内存并将输入字符串复制到其中并返回(strdup() - 它在C中做了什么?),所以我想当我不再需要它时我需要释放它.
从这篇文章:什么是在BISON中调用%析构函数?,我%destructor { free($$); printf("free");} STRING在yacc文件中添加了.
但是,free()即使yylval.sval从返回的新字符串赋值,我也看不到调用strdup().
可能有什么问题?如何释放flex/bison中分配的字符串?
我想如下使用静态分配的sval:
%union {
int ival;
char sval[100]; // char* sval;
}
Run Code Online (Sandbox Code Playgroud)
flex代码现在变为(如果yytext小于100字节,则没有检查代码):
\"[a-zA-Z]+\" {
//yylval.sval = strdup(yytext);
memset(yylval.sval, …Run Code Online (Sandbox Code Playgroud)