非英语语言的编程语言解释器;

如何解决非英语语言的编程语言解释器;

我正在尝试使用其他语言来实现。但是它似乎不能处理插入的字符,这实际上可以用英语工作,我用amharic对其进行了调整,并且我想添加更多内容,例如处理方法是创建编辑器之类。如果有人愿意提供帮助,我将不胜感激。我知道我应该规范unicode字符,但是我不知道该怎么做的有效方法。

function InputStream(input) {
    var pos = 0,line = 1,col = 0;
    return {
        next  : next,peek  : peek,eof   : eof,croak : croak,};
    function next() {
        var ch = input.charAt(pos++);
        if (ch == "\n") line++,col = 0; else col++;
        return ch;
    }
    function peek() {
        return input.charAt(pos);
    }
    function eof() {
        return peek() == "";
    }
    function croak(msg) {
        throw new Error(msg + " (" + line + ":" + col + ")");
    }
}

function TokenStream(input) {
    var current = null;
    var keywords = " ከ ወደ ሌላ ስራ ስራ አውነት ሀሰት ";
    return {
        next  : next,croak : input.croak
    };
    function is_keyword(x) {
        return keywords.indexOf(" " + x + " ") >= 0;
    }
    function is_digit(ch) {
        return /[0-9]/i.test(ch);
    }
    function is_id_start(ch) {
        return /[^\u1380-\u1380f]+[a-z_]/i.test(ch);
    }
    function is_id(ch) {
        return is_id_start(ch) || "?!-<>=0123456789".indexOf(ch) >= 0;
    }
    function is_op_char(ch) {
        return "+-*/%=&|<>!".indexOf(ch) >= 0;
    }
    function is_punc(ch) {
        return "፣፤(){}[]".indexOf(ch) >= 0;
    }
    function is_whitespace(ch) {
        return " \t\n".indexOf(ch) >= 0;
    }
    function read_while(predicate) {
        var str = "";
        while (!input.eof() && predicate(input.peek()))
            str += input.next();
        return str;
    }
    function read_number() {
        var has_dot = false;
        var number = read_while(function(ch){
            if (ch == ".") {
                if (has_dot) return false;
                has_dot = true;
                return true;
            }
            return is_digit(ch);
        });
        return { type: "num",value: parseFloat(number) };
    }
    function read_ident() {
        var id = read_while(is_id);
        return {
            type  : is_keyword(id) ? "kw" : "var",value : id
        };
    }
    function read_escaped(end) {
        var escaped = false,str = "";
        input.next();
        while (!input.eof()) {
            var ch = input.next();
            if (escaped) {
                str += ch;
                escaped = false;
            } else if (ch == "\\") {
                escaped = true;
            } else if (ch == end) {
                break;
            } else {
                str += ch;
            }
        }
        return str;
    }
    function read_string() {
        return { type: "str",value: read_escaped('"') };
    }
    function skip_comment() {
        read_while(function(ch){ return ch != "\n" });
        input.next();
    }
    function read_next() {
        read_while(is_whitespace);
        if (input.eof()) return null;
        var ch = input.peek();
        if (ch == "#") {
            skip_comment();
            return read_next();
        }
        if (ch == '"') return read_string();
        if (is_digit(ch)) return read_number();
        if (is_id_start(ch)) return read_ident();
        if (is_punc(ch)) return {
            type  : "punc",value : input.next()
        };
        if (is_op_char(ch)) return {
            type  : "op",value : read_while(is_op_char)
        };
        input.croak("Can't handle character: " + ch);
    }
    function peek() {
        return current || (current = read_next());
    }
    function next() {
        var tok = current;
        current = null;
        return tok || read_next();
    }
    function eof() {
        return peek() == null;
    }
}

function parse(input) {
    var PRECEDENCE = {
        "=": 1,"||": 2,"&&": 3,"<": 7,">": 7,"<=": 7,">=": 7,"==": 7,"!=": 7,"+": 10,"-": 10,"*": 20,"/": 20,"%": 20,};
    var FALSE = { type: "bool",value: false };
    return parse_toplevel();
    function is_punc(ch) {
        var tok = input.peek();
        return tok && tok.type == "punc" && (!ch || tok.value == ch) && tok;
    }
    function is_kw(kw) {
        var tok = input.peek();
        return tok && tok.type == "kw" && (!kw || tok.value == kw) && tok;
    }
    function is_op(op) {
        var tok = input.peek();
        return tok && tok.type == "op" && (!op || tok.value == op) && tok;
    }
    function skip_punc(ch) {
        if (is_punc(ch)) input.next();
        else input.croak("Expecting punctuation: \"" + ch + "\"");
    }
    function skip_kw(kw) {
        if (is_kw(kw)) input.next();
        else input.croak("Expecting keyword: \"" + kw + "\"");
    }
    function skip_op(op) {
        if (is_op(op)) input.next();
        else input.croak("Expecting operator: \"" + op + "\"");
    }
    function unexpected() {
        input.croak("Unexpected token: " + JSON.stringify(input.peek()));
    }
    function maybe_binary(left,my_prec) {
        var tok = is_op();
        if (tok) {
            var his_prec = PRECEDENCE[tok.value];
            if (his_prec > my_prec) {
                input.next();
                return maybe_binary({
                    type     : tok.value == "=" ? "assign" : "binary",operator : tok.value,left     : left,right    : maybe_binary(parse_atom(),his_prec)
                },my_prec);
            }
        }
        return left;
    }
    function delimited(start,stop,separator,parser) {
        var a = [],first = true;
        skip_punc(start);
        while (!input.eof()) {
            if (is_punc(stop)) break;
            if (first) first = false; else skip_punc(separator);
            if (is_punc(stop)) break;
            a.push(parser());
        }
        skip_punc(stop);
        return a;
    }
    function parse_call(func) {
        return {
            type: "call",func: func,args: delimited("(",")","፣",parse_expression),};
    }
    function parse_varname() {
        var name = input.next();
        if (name.type != "var") input.croak("Expecting variable name");
        return name.value;
    }
    function parse_if() {
        skip_kw("ከ");
        var cond = parse_expression();
        if (!is_punc("{")) skip_kw("ወደ");
        var then = parse_expression();
        var ret = {
            type: "if",cond: cond,then: then,};
        if (is_kw("ሌላ")) {
            input.next();
            ret.else = parse_expression();
        }
        return ret;
    }
    function parse_lambda() {
        return {
            type: "lambda",vars: delimited("(",parse_varname),body: parse_expression()
        };
    }
    function parse_bool() {
        return {
            type  : "bool",value : input.next().value == "አውነት"
        };
    }
    function maybe_call(expr) {
        expr = expr();
        return is_punc("(") ? parse_call(expr) : expr;
    }
    function parse_atom() {
        return maybe_call(function(){
            if (is_punc("(")) {
                input.next();
                var exp = parse_expression();
                skip_punc(")");
                return exp;
            }
            if (is_punc("{")) return parse_prog();
            if (is_kw("if")) return parse_if();
            if (is_kw("አውነት") || is_kw("ሀሰት")) return parse_bool();
            if (is_kw("ስራ") || is_kw("ሥራ")) {
                input.next();
                return parse_lambda();
            }
            var tok = input.next();
            if (tok.type == "var" || tok.type == "num" || tok.type == "str")
                return tok;
            unexpected();
        });
    }
    function parse_toplevel() {
        var prog = [];
        while (!input.eof()) {
            prog.push(parse_expression());
            if (!input.eof()) skip_punc("፤");
        }
        return { type: "prog",prog: prog };
    }
    function parse_prog() {
        var prog = delimited("{","}","፤",parse_expression);
        if (prog.length == 0) return FALSE;
        if (prog.length == 1) return prog[0];
        return { type: "prog",prog: prog };
    }
    function parse_expression() {
        return maybe_call(function(){
            return maybe_binary(parse_atom(),0);
        });
    }
}

function Environment(parent) {
    this.vars = Object.create(parent ? parent.vars : null);
    this.parent = parent;
}
Environment.prototype = {
    extend: function() {
        return new Environment(this);
    },lookup: function(name) {
        var scope = this;
        while (scope) {
            if (Object.prototype.hasOwnProperty.call(scope.vars,name))
                return scope;
            scope = scope.parent;
        }
    },get: function(name) {
        if (name in this.vars)
            return this.vars[name];
        throw new Error("Undefined variable " + name);
    },set: function(name,value) {
        var scope = this.lookup(name);
        if (!scope && this.parent)
            throw new Error("Undefined variable " + name);
        return (scope || this).vars[name] = value;
    },def: function(name,value) {
        return this.vars[name] = value;
    }
};

function evaluate(exp,env) {
    switch (exp.type) {
      case "num":
      case "str":
      case "bool":
        return exp.value;

      case "var":
        return env.get(exp.value);

      case "assign":
        if (exp.left.type != "ተጠቀመም")
            throw new Error("Cannot assign to " + JSON.stringify(exp.left));
        return env.set(exp.left.value,evaluate(exp.right,env));

      case "binary":
        return apply_op(exp.operator,evaluate(exp.left,env),env));

      case "lambda":
        return make_lambda(env,exp);

      case "if":
        var cond = evaluate(exp.cond,env);
        if (cond !== false) return evaluate(exp.then,env);
        return exp.else ? evaluate(exp.else,env) : false;

      case "prog":
        var val = false;
        exp.prog.forEach(function(exp){ val = evaluate(exp,env) });
        return val;

      case "call":
        var func = evaluate(exp.func,env);
        return func.apply(null,exp.args.map(function(arg){
            return evaluate(arg,env);
        }));

      default:
        throw new Error("I don't know how to evaluate " + exp.type);
    }
}

function apply_op(op,a,b) {
    function num(x) {
        if (typeof x != "number")
            throw new Error("Expected number but got " + x);
        return x;
    }
    function div(x) {
        if (num(x) == 0)
            throw new Error("Divide by zero");
        return x;
    }
    switch (op) {
      case "+": return num(a) + num(b);
      case "-": return num(a) - num(b);
      case "*": return num(a) * num(b);
      case "/": return num(a) / div(b);
      case "%": return num(a) % div(b);
      case "&&": return a !== false && b;
      case "||": return a !== false ? a : b;
      case "<": return num(a) < num(b);
      case ">": return num(a) > num(b);
      case "<=": return num(a) <= num(b);
      case ">=": return num(a) >= num(b);
      case "==": return a === b;
      case "!=": return a !== b;
    }
    throw new Error("Can't apply operator " + op);
}

function make_lambda(env,exp) {
    function lambda() {
        var names = exp.vars;
        var scope = env.extend();
        for (var i = 0; i < names.length; ++i)
            scope.def(names[i],i < arguments.length ? arguments[i] : false);
        return evaluate(exp.body,scope);
    }
    return lambda;
}

/* -----[ entry point for NodeJS ]----- */

var globalEnv = new Environment();

globalEnv.def("time",function(func){
    try {
        console.time("time");
        return func();
    } finally {
        console.timeEnd("time");
    }
});

if (typeof process != "undefined") (function(){
    var util = require("util");
    globalEnv.def("ፃፍ",function(val){
        console.log(val);
    });
    globalEnv.def("print",function(val){
        util.print(val);
    });
    var code = "";
    process.stdin.setEncoding("utf8");
    process.stdin.on("readable",function(){
        var chunk = process.stdin.read();
        if (chunk) code += chunk;
    });
    process.stdin.on("end",function(){
        var ast = parse(TokenStream(InputStream(code)));
        evaluate(ast,globalEnv);
    });
})();

这是英文版本,它应该是print的工作方式“ println(” hello world!“);”我想用“ፃፍ(”ሰላም“)፤”其中“打印”和“;”转换为“ፃፍ”和“፤

解决方法

这是很多代码,除了“它似乎无法处理已插入的字符”之外,没有任何解释,这可能意味着几乎任何事情。如果我使用的是Amharic键盘布局,并且知道如何键入,我可能会尝试尝试一下代码,看看有什么问题,但是我没有,而且我也不知道如何使用它,所以我没有尝试。

但是,我认为您的is_idis_id_start函数不太可能起作用。你有:

function is_id_start(ch) {
    return /[^\u1380-\u1380f]+[a-z_]/i.test(ch);
}
function is_id(ch) {
    return is_id_start(ch) || "?!-<>=0123456789".indexOf(ch) >= 0;
}

我很困惑地看到!-<>=是可能的标识符字符,因为它们也是运算符。大概的目的是,如果标识符后面跟有一个运算符,则它们之间必须有空格。但是我不认为这是您在Amharic中遇到的问题。似乎更可能与以下稍微奇怪的正则表达式有关:/[^\u1380-\u1380f]+[a-z_]/i

首先,\u1380f不是单个Unicode转义字符。 \u后面必须紧跟四个十六进制数字,因此f不是转义符的一部分。这只是普通的f。这样就形成了由单个字符consists组成的范围\u1380-\u1380

您的意思是\u1380-\u138f,这可能是453个埃塞俄比亚字母中的16个。我对Amharic的了解非常有限,并且肯定不足以理解这些特殊字符的区别,因此我什至无法开始猜测这是否合理。

但是,您可以在反转的正则表达式中使用该范围;即使进行了更正,[^\u1380-\u138f]匹配的也是该范围内的字符 以外的任何字符。那将包括来自Unicode星系的所有字符,包括许多其他脚本,因此我可以肯定这不是您想要的。

此外,您的ID起始模式实际上是/[^\u1380-\u1380f]+[a-z_]/i,表示“一个或多个[...]后跟拉丁字母字符或下划线”。换句话说,该模式需要至少两个字符进行匹配,首先是一个阿姆哈拉字符(或按书面形式,除了那些阿姆哈拉字符之外的任何字符),然后是拉丁字母。

这显然是错误的,因为您正在将该模式与input.peek()的结果进行匹配,该结果只能是单个字符。因此,保证is_id返回false,这可能与您的问题有关。

我个人认为,使用Unicode Property classes比尝试写下有效标识符字符列表要好得多。 (例如,为什么将标识符限制为仅英语和Amharic?)Ecmascript方便地随附了Unicode技术专家推荐的用于标识符的标准字符集。您可以使用它们:

function is_id_start(ch) {
    return /\p{XID_Start}/u.test(ch);
}
function is_id(ch) {
    return /[\p{XID_Continue}?!-<>=]/u.test(ch);
}

请注意,必须使用u标志来启用Unicode属性的使用。

如果您确实希望将其限制为阿姆哈拉语和拉丁语,则可以通过要求字符也与[\p{Script=Ethiopic}\p{Script=Latin}]匹配来做到这一点。 (您可以使用先行断言来做到这一点。)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-