문제

나는 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

여기 오류는 무엇입니까?

편집 : 오류는 Lexer에있었습니다.

도움이 되었습니까?

해결책

오류는 실제로 Lexer에 있습니다. 당신의 괄호는 마지막으로 끝납니다. Lexer에서, 파서에서 괄호로 나타나지 마십시오.

같은 규칙을 추가하십시오

\)     { return RPAREN; }
\(     { return LPAREN; }

Lexer에게 '(', ')의 모든 발생을 각각 파서에서 lparen과 rparen으로 변경합니다. (또한 토큰 목록을 정의하는 #define lparen 및 rparen이 필요합니다).

참고 : 구문에 대해 잘 모르겠습니다. 백 슬래시가 잘못되었을 수 있습니다.

다른 팁

LISP 문법은 컨텍스트가없는 문법으로 표시 될 수 없으며 YACC는 모든 LISP 코드를 구문 분석 할 수 없습니다. Read-Evaluation 및 Programmable Reader와 같은 LISP 기능 때문입니다. 따라서 임의의 LISP 코드를 읽으려면 전체 LISP를 실행해야합니다. 이것은 모호하고 사용되지 않는 기능이 아니지만 실제로 사용됩니다. EG, CL-interpol, CL-SQL.

목표가 LISP의 하위 집합을 구문 분석하는 것이라면 프로그램 텍스트는 SexPR의 시퀀스입니다.

당신은 비 터미널을 정의해야한다는 점에서 맞습니다. 그것은 sexpr 세트로 정의됩니다. YACC 구문이 확실하지 않습니다. 나는 부분적이다 antlr 파서 생성기와 구문은 다음과 같습니다.

program: sexpr*

0 이상의 sexpr을 나타냅니다.

YACC 구문으로 업데이트 :

program :  /* empty */
        | program sexpr
        ;

YACC는 아니지만 어쨌든 도움이 될 수 있습니다. 여기에 antlr v3의 전체 문법이 설명되어 있습니다 (이 예제에는 중요하지 않기 때문에 Lexer의 문자열을 제외하고 C# 콘솔 출력도 사용하기 때문에 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는 LALR 파서를 생성하고 LALR 파서를 생성하고 ANTLR은 수정 된 재귀 하강이기 때문에 YACC와 정확히 작동하지 않습니다. 그런 식으로 가고 싶다면 Antlr에 대한 C/C ++ 출력 대상이 있습니다.

YACC/Bison Parser가 필요합니까? "LISP 구문의 하위 집합"리더는 C에서 구현하기가 어렵지 않습니다 (read_sexpr 함수로 시작하고 a '('( ')를 볼 때 read_list로 발송합니다. ) '보인다; 그렇지 않으면, 원자를 수집하는 read_atom을 호출하고 더 이상 원자-대응 문자를 읽을 수 없을 때 반환한다).

그러나 Arbritary Common LISP를 읽을 수 있으려면 CL이 독자 런타임을 수정하고 다른 읽기 테이블 런타임 사이에서 전환 할 수 있으므로 공통 LISP를 구현해야합니다. 프로그램 제어하에; LISP의 다른 언어 나 방언으로 작성된 코드를로드하려고 할 때 매우 편리합니다).

내가 YACC와 함께 일한 지 오래되었지만 최상위 비 터미널이 필요합니다. "시도한 시도"와 "작동하지 않는 것"에 대해 더 구체적으로 할 수 있습니까? 또는 그 문제에 대해 오류는 무엇입니까?

또한 YACC가 그러한 구문 라이트 언어에 대해 과잉 일 수 있다고 생각합니다. 재귀 적 출신과 같은 단순한 것이 더 잘 작동 할 수 있습니다.

당신은 시도 할 수 있습니다 이 문법은 여기에 있습니다.

방금 시도했습니다. "YACC LISP 문법"이 잘 작동합니다.

%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