2015-02-09 2 views
0

Я пытаюсь создать простой язык скриптов. Для начала я просто хотел такие вещи, какОшибка анализа с простой грамматикой jison

i = 5; 
i += 3; 
out(i); 

Так я создал следующую грамматику для jison:

%lex 
%% 

\s+     { /* ignore */ } 

"="     { return '='; } 
"+="     { return '+='; } 
"-="     { return '-='; } 
"*="     { return '*='; } 
"/="     { return '/='; } 

"."     { return '.'; } 
"("     { return '('; } 
")"     { return ')'; } 
"{"     { return '{'; } 
"}"     { return '}'; } 

[0-9]+    { return 'NUMBER'; } 
[A-Z]*    { return 'CHAR_SEQUENCE'; } 

<<EOF>>    { return 'EOF'; } 

/lex 

%% 

Program 
    : StatementList EOF 
     { 
      return function() 
      { 
       for(var i = 0; i < $1.length; i++) 
       { 
        $1[i](); 
       } 
      }; 
     } 
    ; 

StatementList 
    : StatementList Statement 
     { $$ = $1.concat($2); } 
    | 
     { $$ = []; } 
    ; 

Statement 
    : AssignStatement 
    | VariableOutput 
    ; 

Operator 
    : "=" 
     { $$ = function(left, right) { left.set(right); }; } 
    | "+=" 
     { $$ = function(left, right) { left.add(right); }; } 
    | "-=" 
     { $$ = function(left, right) { left.remove(right); }; } 
    | "*=" 
     { $$ = function(left, right) { left.multiplicate(right); }; } 
    | "/=" 
     { $$ = function(left, right) { left.divide(right); }; } 
    ; 


VariableOutput 
    : 'out(' CHAR_SEQUENCE ')' ';' 
     { 
      $$ = function() 
      { 
       var t = new Tellraw("Output: "); 
       t.extra.push(vars[$1].toTellrawExtra()); 
       t.tell(new Entities.Player("@a")); 
      }; 
     } 
    ; 

AssignStatement 
    : CHAR_SEQUENCE Operator CHAR_SEQUENCE ';' 
     { 
      $$ = function() 
      { 
       Util.assert(typeof vars[$3] != 'undefined', "Unknown identifier '"+$3+"'"); 

       if(typeof vars[$1] == 'undefined') 
        vars[$1] = vars[$3].constructor.call(); 

       $2(vars[$1], vars[$3]); 
      }; 
     } 
    | CHAR_SEQUENCE Operator '"' CHAR_SEQUENCE '"' ';' 
     { 
      $$ = function() 
      { 
       if(typeof vars[$1] == 'undefined') 
        vars[$1] = new Runtime.String($3); 

       $2(vars[$1], $3); 
      }; 
     } 
    | CHAR_SEQUENCE Operator NUMBER ';' 
     { 
      $$ = function() 
      { 
       if(typeof vars[$1] == 'undefined') 
        vars[$1] = new Runtime.Integer($3); 

       $2(vars[$1], $3); 
      }; 
     } 
    ; 

Он генерирует синтаксический анализатор не жалуясь о грамматике. Моя проблема заключается в том, что когда я

parser.parse('i=5;out(i);')(); 

Я получаю эту ошибку

Parse error on line 1: 
i = 5;out(i); 
^ 
Expecting '=', '+=', '-=', '*=', '/=', got 'CHAR_SEQUENCE' 

Это совершенно путает меня:/нет правила, которое ожидает оператора в первом. Единственными правилами, ожидающими оператора, являются AssignStatements, но все они ожидают, что CHAR_SQUENCE станет первым объектом.

Я делаю что-то неправильно? Или почему это не работает? Если вам нужна дополнительная информация, не стесняйтесь спросить :)

ответ

1

Вы ожидаете i быть CHAR_SEQUENCE но CHAR_SEQUENCE является [A-Z]*, что сказать, только заглавные буквы. Вы, вероятно, хотели чего-то вроде [A-Za-z_][A-Za-z_0-9]*. Таким образом, lexer не распознает i.

Однако, он распознает пустой CHAR_SEQUENCE. В jison, в отличие от flex, шаблоны, которые могут соответствовать пустой строке, будут делать это, и их почти всегда следует избегать.

+0

спасибо, что это работает сейчас :) – M4GNV5

0

Возможно ли, что при использовании

[A-Z]*    { return 'CHAR_SEQUENCE'; } 

с * вместо + вы рассматриваете пустую строку в качестве CHAR_SEQUENCE, а затем парсер нахождение двух CHAR_SEQUENCE вместо одного?