寻找关于为JS / CC创建语法的一点帮助和指导

时间:2011-12-02 06:39:49

标签: grammar jscc

关于我的上一个问题How would I write an interpreter for this in javascript?我试图创建一个JS/CC语法。如果您想尝试我的语法,他们会安装live程序,只需将其复制并粘贴到顶部框中,点击Build然后点击Run

结果应该运行语法底部的小程序,即:

popup 'String Literal'
popup 42
set myVariable to 10
popup myVariable

运行时你应该得到3个警报,最后一个应该是10,但是它的0.我的完整语法是下面的,它是他们样本的修剪版本。我可以使用一些帮助来解释为什么最后一次警报是0而不是10,正如我所期望的那样。

[*

//Structs
function NODE()
{
    var type;
    var value;
    var children;
}

//Defines
var NODE_OP     = 0;
var NODE_VAR    = 1;
var NODE_CONST  = 2;

var OP_NONE     = -1;
var OP_ASSIGN   = 0;
var OP_POPUP    = 7;

var OP_ADD      = 16;
var OP_SUB      = 17;
var OP_DIV      = 18;
var OP_MUL      = 19;
var OP_NEG      = 20;

//Management functions
function createNode(type, value, childs) {
    var n = new NODE();
    n.type = type;
    n.value = value;    
    n.children = new Array();

    for(var i = 2; i < arguments.length; i++)
        n.children.push(arguments[i]);

    return n;
}

var v_names = new Array();
var v_values = new Array();

//Interpreting function
function letvar(vname, value) {
    var i;
    for(i = 0; i < v_names.length; i++)
        if(v_names[i].toString() == vname.toString())
            break;

    if(i == v_names.length) {
        v_names.push(vname);
        v_values.push(0);
    }

    v_values[i] = value;
}

function getvar(vname) {
    var i;
    for(i = 0; i < v_names.length; i++)
        if(v_names[i].toString() == vname.toString())
            return v_values[i];

    return 0;
}

function execute(node) {
    var ret = 0;

    if(!node)
        return 0;

    switch(node.type)
    {
        case NODE_OP:
            switch( node.value )
            {
                case OP_NONE:
                    if(node.children[0])
                        execute(node.children[0]);          
                    if(node.children[1])
                        ret = execute(node.children[1]);
                    break;
                case OP_ASSIGN:
                    letvar(node.children[0], execute(node.children[1]));
                    break;
                case OP_POPUP:
                    alert(execute(node.children[0]));
                    break;
                case OP_ADD:
                    ret = execute( node.children[0] ) + execute( node.children[1] );
                    break;
                case OP_SUB:
                    ret = execute( node.children[0] ) - execute( node.children[1] );
                    break;
                case OP_DIV:
                    ret = execute( node.children[0] ) / execute( node.children[1] );
                    break;
                case OP_MUL:
                    ret = execute( node.children[0] ) * execute( node.children[1] );
                    break;
                case OP_NEG:
                    ret = execute( node.children[0] ) * -1;
                    break;
            }
            break;

        case NODE_VAR:
            ret = getvar(node.value);
            break;

        case NODE_CONST:
            ret = node.value;
            break;
    }

    return ret;
}

*]


!   ' |\r|\t'

    "SET"
    "POPUP"
    "BEGIN"
    "END"
    '\n'                            EOL
    "TO"
    "ADD"
    "SUB"
    "NEG"
    "DIV"
    "MUL"
    '\('
    '\)'
    '#'
    '[A-Za-z_][A-Za-z0-9_]*'        Identifier
    '\'([^\']|\'\')*\''             String      [* %match = %match.substr(1, %match.length - 2);
                                                   %match = %match.replace(/''/g, "\'");    *]
    '[0-9]+'                        Integer
    '[0-9]+\.[0-9]*|[0-9]*\.[0-9]+' Float
    ;

##

Program:
      Program Stmt                              [* execute(%2); *]
    |
    ;

Stmt:
      POPUP Expression EOL                      [* %% = createNode(NODE_OP, OP_POPUP, %2); *]
    | SET Identifier TO Expression EOL          [* %% = createNode(NODE_OP, OP_ASSIGN, %1, %3); *]
    | "BEGIN" Stmt_List "END"                   [* %% = %2; *]
    | EOL                                       [* %% = createNode(NODE_OP, OP_NONE); *]
    ;

Stmt_List:
      Stmt_List Stmt                            [* %% = createNode(NODE_OP, OP_NONE, %1, %2); *]
    |
    ;

Expression:
      AddSubExp
    ;

AddSubExp:
      AddSubExp "SUB" MulDivExp                 [* %% = createNode(NODE_OP, OP_SUB, %1, %3); *]
    | AddSubExp "ADD" MulDivExp                 [* %% = createNode(NODE_OP, OP_ADD, %1, %3); *]
    | MulDivExp
    ;

MulDivExp:
      MulDivExp "MUL" NegExp                    [* %% = createNode(NODE_OP, OP_MUL, %1, %3); *]
    | MulDivExp "DIV" NegExp                    [* %% = createNode(NODE_OP, OP_DIV, %1, %3); *]
    | NegExp
    ;

NegExp:
      "NEG" Value                               [* %% = createNode(NODE_OP, OP_NEG, %2); *]
    | Value
    ;

Value:
      Integer                                   [* %% = createNode(NODE_CONST, %1); *]
    | Float                                     [* %% = createNode(NODE_CONST, %1); *]
    | String                                    [* %% = createNode(NODE_CONST, %1); *]
    | Identifier                                [* %% = createNode(NODE_VAR, %1); *]
    | '(' Expression ')'                        [* %% = %2; *]
    ;


[*

var str = "";
str += "popup 'String Literal'\n";
str += "popup 42\n";
str += "set myVariable to 10\n";
str += "popup myVariable\n";

var error_cnt   = 0;
var error_off   = new Array();
var error_la    = new Array();

if( ( error_cnt = __parse( str, error_off, error_la ) ) > 0 )
{
    for( i = 0; i < error_cnt; i++ )
        alert( "Parse error near >" 
            + str.substr( error_off[i], 30 ) + "<, expecting \"" + error_la[i].join() + "\"" );
}
*]

1 个答案:

答案 0 :(得分:1)

在此规则中看起来您的索引可能已关闭:

    | SET Identifier TO Expression EOL          [* %% = createNode(NODE_OP, OP_ASSIGN, %1, %3); *]

你的意思是

    createNode(NODE_OP, OP_ASSIGN, %2, %4);

...