0

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

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

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

4

2 回答 2

1

您期望i是 a CHAR_SEQUENCEbut CHAR_SEQUENCEis [A-Z]*,也就是说,只有大写字母。您可能想要类似[A-Za-z_][A-Za-z_0-9]*. 所以词法分析器根本无法识别i

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

于 2015-02-09T16:06:09.070 回答
0

有没有可能当你使用

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

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

于 2015-02-09T15:46:35.630 回答