2016-06-01 6 views
0

Это код, который у меня есть:Почему мои синтаксические ошибки в Jison не распространяются?

%lex 
%options flex 

%{ 
// Used to store the parsed data 
if (!('regions' in yy)) { 
    yy.regions = { 
     settings: {}, 
     tables: [], 
     relationships: [] 
    }; 
} 
%} 

text    [a-zA-Z][a-zA-Z0-9]* 

%% 

\n\s*    return 'NEWLINE'; 
[^\S\n]+   ; // ignore whitespace other than newlines 
"."     return '.'; 
","     return ','; 
"-"     return '-'; 
"="     return '='; 
"=>"    return '=>'; 
"<="    return '<='; 
"["     return '['; 
"settings]"   return 'SETTINGS'; 
"tables]"   return 'TABLES'; 
"relationships]" return 'RELATIONSHIPS'; 
"]"     return ']'; 
{text}    return 'TEXT'; 
<<EOF>>    return 'EOF'; 

/lex 

%left ',' 

%start source 

%% 

source 
    : content EOF 
     { 
      console.log(yy.regions); 
      console.log("\n" + JSON.stringify(yy.regions)); 
      return yy.regions; 
     } 
    | NEWLINE content EOF 
     { 
      console.log(yy.regions); 
      console.log("\n" + JSON.stringify(yy.regions)); 
      return yy.regions; 
     } 
    | NEWLINE EOF 
    | EOF 
    ; 

content 
    : '[' section content 
    | '[' section 
    ; 

section 
    : SETTINGS NEWLINE settings_content 
    | TABLES NEWLINE tables_content 
    | RELATIONSHIPS NEWLINE relationships_content 
    ; 

settings_content 
    : settings_line NEWLINE settings_content 
    | settings_line NEWLINE 
    | settings_line 
    ; 

settings_line 
    : text '=' text 
     { yy.regions.settings[$1] = $3; } 
    ; 

tables_content 
    : tables_line NEWLINE tables_content 
    | tables_line NEWLINE 
    | tables_line 
    ; 

tables_line 
    : table_name 
     { yy.regions.tables.push({ name: $table_name, fields: [] }); } 
    | field_list 
     { 
      var tableCount = yy.regions.tables.length; 
      var tableIndex = tableCount - 1; 
      yy.regions.tables[tableIndex].fields.push($field_list); 
     } 
    ; 

table_name 
    : '-' text 
     { $$ = $text; } 
    ; 

field_list 
    : text 
     { $$=[]; $$.push($text); } 
    | field_list ',' text 
     { $field_list.push($text); $$ = $field_list; } 
    ; 

relationships_content 
    : relationships_line NEWLINE relationships_content 
    | relationships_line NEWLINE 
    | relationships_line 
    ; 

relationships_line 
    : relationship_key '=>' relationship_key 
     { 
      yy.regions.relationships.push({ 
       pkTable: $1, 
       fkTable: $3 
      }); 
     } 
    | relationship_key '<=' relationship_key 
     { 
      yy.regions.relationships.push({ 
       pkTable: $3, 
       fkTable: $1 
      }); 
     } 
    ; 

relationship_key 
    : text '.' text 
     { $$ = { name: $1, field: $3 }; } 
    | text 
     { $$ = { name: $1 }; } 
    ; 

text 
    : TEXT 
     { $$ = $TEXT; } 
    ; 

Он используется для анализа такого рода кода:

[settings] 
DefaultFieldType = string 

[tables] 
-table1 
id, int, PK 
username, string, NULL 
password, string 

-table2 
id, int, PK 
itemName, string 
itemCount, int 

[relationships] 
table1 => table2 
foo.test => bar.test2 

В этом виде JSON:

{ settings: { DefaultFieldType: 'string' }, 
    tables: 
    [ { name: 'table1', fields: [Object] }, 
    { name: 'table2', fields: [Object] } ], 
    relationships: 
    [ { pkTable: [Object], fkTable: [Object] }, 
    { pkTable: [Object], fkTable: [Object] } ] } 

Однако я не» t получить синтаксическую ошибку. Когда я иду в Jison demo и попытаться разобрать 5*PI 3^2, я получаю следующее сообщение об ошибке:

Parse error on line 1: 
5*PI 3^2 
-----^ 
Expecting 'EOF', '+', '-', '*', '/', '^', ')', got 'NUMBER' 

, который, как ожидается. Но когда я изменить последнюю строку кода, который я желаю разобрать из:

foo.test => bar.test2 

к чему-то вроде

foo.test => a bar.test2 

я получаю следующее сообщение об ошибке:

throw new _parseError(str, hash); 
    ^
TypeError: Function.prototype.toString is not generic 

Я проследил это к сгенерированному парсерному коду, который выглядит следующим образом:

if (hash.recoverable) { 
    this.trace(str); 
} else { 
    function _parseError (msg, hash) { 
     this.message = msg; 
     this.hash = hash; 
    } 
    _parseError.prototype = Error; 

    throw new _parseError(str, hash); 
} 

Итак, это заставляет меня думать, что что-то не так в том, как я структурировал свой код и как я обрабатывал синтаксический анализ, но я понятия не имею, что это может быть.

Похоже, что это могло бы иметь отношение к error recovery. Если это правильно, как это предполагается использовать? Должен ли я добавить правило «ошибка» вверх для каждого элемента до исходного корня?

ответ

1

Ваша грамматика работает как ожидалось на демо-странице Jison, по крайней мере, с браузером, который я использую (Firefox 46.0.1). От количества деятельности в хранилище мерзавца вокруг кода, который вы цитируете, я подозреваю, что версия jison вы используете имеет один из ошибок:

I думаю версия jison на демо-странице старше, но не новее, поэтому, если захват текущего кода из github не работает, вы можете попробовать использовать более старую версию.