为什么我在 Jison 中的语法错误不是 "propagated"?
Why are my syntax errors in Jison not being "propagated"?
这是我的代码:
%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[] = ; }
;
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: ,
fkTable:
});
}
| relationship_key '<=' relationship_key
{
yy.regions.relationships.push({
pkTable: ,
fkTable:
});
}
;
relationship_key
: text '.' text
{ $$ = { name: , field: }; }
| text
{ $$ = { name: }; }
;
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] } ] }
但是我没有收到语法错误。当我转到 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有点关系。如果那是正确的,那应该如何使用?我是否应该将 'error' 规则向上添加到每个元素,一直到源根目录?
您的语法在 Jison 演示页面中似乎按预期工作,至少在我使用的浏览器 (Firefox 46.0.1) 中是这样。根据您引用的代码 git 存储库中的 activity 数量,我怀疑您使用的 jison 版本有以下错误之一:
我 认为 演示页面上的 jison 版本较旧,而不是较新,因此如果从 github 获取当前代码不起作用,您可以尝试使用旧版本。
这是我的代码:
%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[] = ; }
;
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: ,
fkTable:
});
}
| relationship_key '<=' relationship_key
{
yy.regions.relationships.push({
pkTable: ,
fkTable:
});
}
;
relationship_key
: text '.' text
{ $$ = { name: , field: }; }
| text
{ $$ = { name: }; }
;
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] } ] }
但是我没有收到语法错误。当我转到 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有点关系。如果那是正确的,那应该如何使用?我是否应该将 'error' 规则向上添加到每个元素,一直到源根目录?
您的语法在 Jison 演示页面中似乎按预期工作,至少在我使用的浏览器 (Firefox 46.0.1) 中是这样。根据您引用的代码 git 存储库中的 activity 数量,我怀疑您使用的 jison 版本有以下错误之一:
我 认为 演示页面上的 jison 版本较旧,而不是较新,因此如果从 github 获取当前代码不起作用,您可以尝试使用旧版本。