2014-09-24 2 views
3

원래 Perl (참조 Chessa# on github 참조)을 기반으로 작성한 minilanguage를 다시 작성하지만 의미를 적용 할 때 여러 가지 문제가 있습니다. grako의 규칙 우선 순위 문제

Here is the grammar

:

(* integers *) 
DEC = /([1-9][0-9]*|0+)/; 
int = /(0b[01]+|0o[0-7]+|0x[0-9a-fA-F]+)/ | DEC; 
(* floats *) 
pointfloat = /([0-9]*\.[0-9]+|[0-9]+\.)/; 
expfloat = /([0-9]+\.?|[0-9]*\.)[eE][+-]?[0-9]+/; 
float = pointfloat | expfloat; 
list = '[' @+:atom {',' @+:atom}* ']'; 
(* atoms *) 
identifier = /[_a-zA-Z][_a-zA-Z0-9]*/; 
symbol = int  | 
     float  | 
     identifier | 
     list; 
(* functions *) 
arglist = @+:atom {',' @+:atom}*; 
function = identifier '(' [arglist] ')'; 
atom = function | symbol; 
prec8 = '(' atom ')' | atom; 
prec7 = [('+' | '-' | '~')] prec8; 
prec6 = prec7 ['!']; 
prec5 = [prec6 '**'] prec6; 
prec4 = [prec5 ('*' | '/' | '%' | 'd')] prec5; 
prec3 = [prec4 ('+' | '-')] prec4; 
(* <| and >| are rotate-left and rotate-right, respectively. They assume the nearest C size. *) 
prec2 = [prec3 ('<<' | '>>' | '<|' | '>|')] prec3; 
prec1 = [prec2 ('&' | '|' | '^')] prec2; 
expr = prec1 $; 

내가 실행 해요 문제는 어떤 공백 운영자 및 다음 영숫자 문자열 사이에 존재하지 않을 때 d 운영자가 식별자 규칙에 들어갔습니다 점이다. 문법 자체는 LL (2)이지만 문제가있는 곳을 이해하지 못합니다.

예를 들어, 4d64d6으로 해석되므로 파서를 중지합니다. 여기서 d6은 식별자입니다. 무엇이 발생해야하는지는 4d6으로 해석되며 d이 연산자로 사용됩니다. LL 파서에서는 이것이 사실 일 것이다.

가능한 해결책은 d이 식별자를 시작하지 못하도록하는 것이지만 drop과 같은 기능의 이름 지정을 허용하지 않습니다.

+1

명료성을 위해 이것은 주사위 봇용입니다. – Aerdan

+0

이 질문은 너무 광범위합니다. 특정 코딩 문제에 초점을 맞춘보다 정확한 질문을 게시 할 수 있습니다. 그렇지 않으면 게시물이 너무 광범위하거나 불분명 한 질문으로 인해 닫힐 위험이 있습니다 – joaquin

+0

2 및 3은 작동하지 않습니다. 꽤 모호합니다. 나는 당신이 다른 사람들을 제대로 공식화 할 때까지 질문을 1로 좁히는 것이 좋습니다. – dfeuer

답변

1

예를 들어, Grako는 기본적으로 nameguard 기능을 사용하며, 이 앞에있을 때 d을 구문 분석 할 수 없습니다.

는 기능을 사용하지 Buffer 자신을 인스턴스화하고 생성 된 파서의 인스턴스에 전달하려면

from grako.buffering import Buffer 
from myparser import MyParser 

# get the text 
parser = MyParser() 
parser.parse(Buffer(text, nameguard=False), 'expre') 

Bitbucket repository에 Grako의 팁 버전은 생성 된 파서에 --no-nameguard 명령 줄 옵션을 추가합니다.

+1

[Bitbucket 저장소]의 Grako 팁 버전 (https://bitbucket.org/apalala/grako)은 생성 된 파서에'--no-nameguard'' 명령 행 옵션을 추가합니다. – Apalala

+1

아하, 고마워. 그것은 문제를 해결합니다 .... – Aerdan

+1

재미 있습니다 ...'nameguard = False'는'd' 연산자를 수정하지만 또한 10 진수가 아닌 정수 (예 :'0b1','0o5','0xF')를 ~ 파싱에 실패했다. – Aerdan

3

Perl에서는 일반적인 BNF 파서 인 Marpa을 사용할 수 있습니다.이 파서는 일반화 된 우선 순위와 결합 성 (예 :.

:start ::= Script 
Script ::= Expression+ separator => comma 
comma ~ [,] 
Expression ::= 
    Number bless => primary 
    | '(' Expression ')' bless => paren assoc => group 
    || Expression '**' Expression bless => exponentiate assoc => right 
    || Expression '*' Expression bless => multiply 
    | Expression '/' Expression bless => divide 
    || Expression '+' Expression bless => add 
    | Expression '-' Expression bless => subtract 

전체 동작 예제는 here입니다. 프로그래밍 언어는 C parser based on Marpa입니다.

희망이 도움이됩니다.