首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >意外WS令牌:“”

意外WS令牌:“”
EN

Stack Overflow用户
提问于 2022-09-04 22:08:53
回答 1查看 61关注 0票数 0

我正在使用nearley.js和moo.js编写一种编程语言。对于moo.js,有一个NL,这意味着新的行正则匹配,而我的是`/\r\n+/,但似乎存在一个问题。在我正在学习的教程中,它说

代码语言:javascript
复制
Unexpected WS token: "    ". Instead, I was expecting to see one of the following:

A identifier token based on:
    var_assign →  ● %identifier _ "=" _ expr
A identifier token based on:
    fun_call →  ● %identifier _ "(" _ fun_call$ebnf$1 ")"

    at Parser.feed (C:\Users\mcqui\OneDrive\Desktop\Programming language for capstones\node_modules\nearley\lib\nearley.js:343:27)
    at main (C:\Users\mcqui\OneDrive\Desktop\Programming language for capstones\parse.js:15:12)

我不知道该怎么做,因为我检查了所有的东西,似乎没有用。这是我的lexer.js文件:

代码语言:javascript
复制
const moo = require('moo')
const fs = require("mz/fs")

let lexer = moo.compile({
  WS:      /[ \t]+/,
  comment: /\/\/.*?$/,
  number:  /0|[1-9][0-9]*/,
  string:  /"(?:\\["\\]|[^\n"\\])*"/,
  lparen:  '(',
  rparen:  ')',
  lbrace:  '{',
  rbrace:  '}',
  identifier: /[a-zA-Z][a-zA-Z_0-9]*/,
  fatarrow: '=>',
  assign: '=',
  NL: { match: /[\r\n]+/, lineBreaks: true }
});

module.exports = lexer;


async function main(){
    const code = (await fs.readFile("main.kpp")).toString()
    lexer.reset(code)
    while (true){
        const token = lexer.next();
        if(!token){
            break;
        }
        console.log(token);
    }
}

这是我的parse.js文件:

代码语言:javascript
复制
const nearley = require("nearley");
const grammar = require("./kpp.js");
const fs = require('mz/fs');

async function main() {

    const filename = process.argv[2];
    if(!filename){
        console.log("Provide a .kpp file");
        return;
    }

    const code = (await fs.readFile(filename)).toString();
    const parser = new nearley.Parser(nearley.Grammar.fromCompiled(grammar));
    parser.feed(code);
    if(parser.results.length > 1){
        console.log('Error');
    } else if (parser.results.length == 1){
        const ast = parser.results[0];
        const outputFilename = filename.replace('.kpp', '.ast');
        await fs.writeFile(outputFilename, JSON.stringify(ast, null, " "))
        console.log(`WROTE ${outputFilename}.`)
    } else{
        console.log("Parse error")
    }

}

main().catch(err => console.log(err.stack));

下面是我正在运行的文件(在我自己的编程语言中):

代码语言:javascript
复制
f = () => 1
g = (a b) => add(multiply(2 a) b)
h = (x y) => {
    show("x=" x)
    show("y=" y)
    g(x y)
}
result = h(3 4)
show("result =" result)
show("f =" f())
show("f(gf f) =" g(f() f()))

下面是nearley.js配置文件:

代码语言:javascript
复制
@{%
const myLexer = require("./lexer")
%}

@lexer myLexer

statements
    ->statement
    {%
        (data) => {
            return [data[0]]
        }
    %}
    | statements %NL statement
    {%
        (data) => {
            return [...data[0], data[2]]
        }
    %}

statement
    -> var_assign  {% id %}
    | fun_call     {% id %}



var_assign
    -> %identifier _ "=" _ expr
        {%
            (data) => {
                return {
                    type: "var_assign",
                    var_name: data[0],
                    value: data[4]
                }
            }
        %}

fun_call
    -> %identifier _ "(" _ (arg_list _):? ")"
    {%
        (data) => {
            return {
                type: 'fun_call',
                fun_name: data[0],
                arguments: data[4] ? data[4][0] : []
            }
        }
    %}

arg_list
    -> expr
    {%
        (data) => {
            return [data[0]]
        }
    %}
    | arg_list __ expr
    {%
        (data) => {
            return [...data[0], data[2]]
        }
    %}

expr
    -> %string    {% id %}
    | %number     {% id %}
    | %identifier {% id %}
    | fun_call    {% id %}
    | lamba       {% id %}

lamba -> "(" _ (param_list _):? ")" _ "=>" _ lamba_body
    {%
        (data) => {
            return {
                type: "lamba",
                parameters: data[2] ? data[2][0] : [],
                body: data[7]
            }
        }
    %}

param_list
    -> %identifier (__ %identifier):*
    {%
        (data) => {
            const repeatedPieces = data[1];
            const restParams = repeatedPieces.map(piece => piece[1])
            return [data[0], ...restParams]
        }
    %}

lamba_body
    -> expr
        {%
            (data) => {
                return [data[0]];
            }
        %}
    | "{" _ %NL statements %NL _ "}"
        {%
            (data) => {
                return data[3];
            }
        %}

_ -> %WS:*

__ -> %WS:+
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-09-04 22:27:55

这里的问题来自于这样一个事实:您没有指定任何关于表的期望的内容。statements %NL statement清楚地告诉解析器,您所期望的只是一个或多个新行字符。我建议您不要单独指定新行作为字符串的结尾,而应该使用空格(换行符):*代替。您还可以使用类似的技术,即这个雷克萨斯这个空格规则使用的技术。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73603121

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档