codemirror / codemirror5

In-browser code editor (version 5, legacy)
http://codemirror.net/5/
MIT License
26.82k stars 4.97k forks source link

Peg.js mode doesn't support JavaScript embeds #6850

Open jcubic opened 2 years ago

jcubic commented 2 years ago

Just found that CodeMirror PEG.js mode doesn't work properly if you use JavaScript prefix in the grammar.

PEG.js (and Peggy maintained fork) supports code like this that break the mode:

{

    var heredoc_begin = null;
    var $$__m; // result of match
    var variable_prefix = '$_';
    var match_identifer = make_identifier('$$__m');
    var match_method = make_identifier('match');

    function make_if(test, body, alternative) {
        return {
            "type": "IfStatement",
            "test": test,
            "consequent": make_block(body),
            "alternate": alternative
        };
    }
}

Start = statements:(!"end" _ statement* / _) {
    return {
        "type": "Program",
        "body": [{
            "type": "ExpressionStatement",
            "expression": {
                "type": "CallExpression",
                "callee": {
                    "type": "FunctionExpression",
                    "id": null,
                    "async": true,
                    "params": [],
                    "body": {
                        "type": "BlockStatement",
                        "body": statements[2].filter(Boolean)
                    }
                },
                "arguments": []
            }
        }]
    };
}

Peggy also supports {{ <JavaScript> }} not sure if it's also supported by PEG.js.

This copy/pasted part of my parser. As you can see, GitHub supports JavaScript code snippets like this.

I think that this should be easy to fix because adding:

start = '' 

in front fix the issue.

I can check the mode file and see if I can fix it.

jcubic commented 2 years ago

It may be something more complex. When PegJS mode initially loaded with JavaScript mode, it looks correct. But after editing it the colors are broken. I may create Video to show this.

Also found this code problematic:

function_definition = _ "def" _ name:variable _ "(" args:(variable _ ","? _)* ")" _  body:statement* _ "end" _ {
    const fn_name = name.name.replace(/\$_/, '');
    if (available_commands.includes(fn_name)) {
        const error = new Error(`invalid function name, '${fn_name}' is a command`);
        error.location = move_location(location(), 4, fn_name.length + 4);
        throw error;
    }
    var args = args.map(function(arg) { return arg[0]; });
    return {
        "type": "FunctionDeclaration",
        "id": name,
        "params": args,
        "async": true,
        "body": {
            "type": "BlockStatement",
            "body": body
        }
    };
}

pegJS