我想建立一个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
    | '+'
    | '-'
    | '*'
    | '^'
    | '/'
    ;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top