题
我想建立一个Lisp语法。很简单吧?显然没有。
我提出这些输入和接收错误...
( 1 1)
23 23 23
ui ui
这是语法...
%%
sexpr: atom {printf("matched sexpr\n");}
| list
;
list: '(' members ')' {printf("matched list\n");}
| '('')' {printf("matched empty list\n");}
;
members: sexpr {printf("members 1\n");}
| sexpr members {printf("members 2\n");}
;
atom: ID {printf("ID\n");}
| NUM {printf("NUM\n");}
| STR {printf("STR\n");}
;
%%
尽可能接近我可以告诉我需要定义为一个程序,在其上整个解析树可以挂的单一非末端。但是,我尝试过了,它似乎并没有工作。
编辑 - 这是我的 “顶终端” 的方法:
program: slist;
slist: slist sexpr | sexpr;
但是它允许的问题,例如:
( 1 1
EDIT2:该FLEX代码是...
%{
#include <stdio.h>
#include "a.yacc.tab.h"
int linenumber;
extern int yylval;
%}
%%
\n { linenumber++; }
[0-9]+ { yylval = atoi(yytext); return NUM; }
\"[^\"\n]*\" { return STR; }
[a-zA-Z][a-zA-Z0-9]* { return ID; }
.
%%
过匹配的一个例子...
(1 1 1)
NUM
matched sexpr
NUM
matched sexpr
NUM
matched sexpr
(1 1
NUM
matched sexpr
NUM
matched sexpr
这里有什么错误?
编辑:在词法分析器误差
。解决方案
该错误是真的在词法分析器。你的括号最终成为最后一个“”在词法分析器,并且不显示为在解析器括号中。
中添加规则等
\) { return RPAREN; }
\( { return LPAREN; }
要词法分析器和改变的“(”,“)”所有出现到LPAREN和RPAREN分别在解析器。 (还,你需要#定义LPAREN和RPAREN在此定义您的令牌列表)
请注意:我不知道有关语法,可能是反斜线是错误的。
。其他提示
Lisp的语法不能被表示为上下文无关文法,和yacc不能解析所有Lisp代码。 正是由于口齿不清的功能,如阅读,评价和可编程读者。因此,为了以防读取任意Lisp代码,你需要有一个完整的运行口齿不清。这是不是有些晦涩,不常用的功能,但它实际上是使用。例如,CL-INTERPOL,CL-SQL。
如果目标是解析口齿不清的子集,则该程序的文本是sexprs的序列。
您是在您需要定义一个非终端正确。这将被定义为一组sexpr的。我不知道该YACC语法是的。我偏爱 ANTLR 获得解析器生成器和语法是:
program: sexpr*
指示0以上sexpr。
更新与YACC语法:
program : /* empty */
| program sexpr
;
不在YACC,但可能会有所帮助,无论如何,这里是在ANTLR v3的一个完整的语法为你描述(在词法分析器中排除的字符串,因为它不是在这个例子中很重要的情况下工作,还使用C#控制台输出,因为这是我与测试它):
program: (sexpr)*;
sexpr: list
| atom {Console.WriteLine("matched sexpr");}
;
list:
'('')' {Console.WriteLine("matched empty list");}
| '(' members ')' {Console.WriteLine("matched list");}
;
members: (sexpr)+ {Console.WriteLine("members 1");};
atom: Id {Console.WriteLine("ID");}
| Num {Console.WriteLine("NUM");}
;
Num: ( '0' .. '9')+;
Id: ('a' .. 'z' | 'A' .. 'Z')+;
Whitespace : ( ' ' | '\r' '\n' | '\n' | '\t' ) {Skip();};
如在YACC因为YACC生成并LALR解析器而ANTLR是修饰的递归下降这将不完全工作。这里是一个ANTLR C / C ++输出的目标,如果你想要去的方式。
你neccesarily需要YACC /野牛分析器? A“读口齿不清语法的一个子集”的读者是不是很难用C来实现(先从read_sexpr功能,派遣一个read_list当你看到一个“(”,这反过来构建包含sexprs的名单,直到' )”被看作;否则,调用收集的原子,并返回它时,它不再能够读原子构成字符)read_atom
不过,如果你想能够阅读arbritary Common Lisp的,你需要(在最差)实施的Common Lisp,如CL可以修改读写器运行时(甚至是不同的读表之间切换运行时程序的控制下;非常方便,当你想加载用其它语言编写或LISP的方言代码)
它一直以来我与YACC工作了很长一段时间,但你需要一个顶级的非终端。你能具体谈谈“尝试过”和“它似乎没有工作”?或者,对于这个问题,有什么错误?
我还怀疑YACC可能是矫枉过正这样的语法轻语。简单的东西(如递归下降)可能更好地工作。
您可以尝试这个语法这里。
我刚刚试了一下,我的 “YACC口齿不清语法” 正常工作:
%start exprs
exprs:
| exprs expr
/// if you prefer right recursion :
/// | expr exprs
;
list:
'(' exprs ')'
;
expr:
atom
| list
;
atom:
IDENTIFIER
| CONSTANT
| NIL
| '+'
| '-'
| '*'
| '^'
| '/'
;