用简单的jison语法分析错误

Parse error with simple jison grammar

本文关键字:语法分析 错误 jison 简单      更新时间:2023-09-26

我正在尝试创建一种简单的脚本语言。一开始我只是想要像这样的东西

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_QUENCE作为第一个对象。

我做错什么了吗?或者为什么它不起作用?如果您需要任何进一步的信息,请随时询问:)

您希望iCHAR_SEQUENCE,但CHAR_SEQUENCE[A-Z]*,也就是说,只有大写字母。你可能想要[A-Za-z_][A-Za-z_0-9]*这样的东西。因此lexer根本没有识别出i

然而,它正在识别一个空的CHAR_SEQUENCE。在jison中,与flex不同,可以匹配空字符串的模式会这样做,并且几乎总是应该避免。

当您使用时

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

使用*而不是+,您将空字符串视为CHAR_SEQUENCE,然后解析器会找到两个CHAR_SEQUNCE而不是一个?