idea使用monaco_使用Monaco和ANTLR编写基于浏览器的编辑器

2023-10-27

idea使用monaco

这是关于为我们将要定义的新语言创建基于浏览器的编辑器的教程。

我们将使用两个组件:

  1. Monaco :它是一个很棒的基于浏览器的编辑器(或一个Web编辑器:如您所愿)
  2. ANTLR :这是我们喜欢用来构建各种解析器的解析器生成器

我们将为一种简单的语言构建一个编辑器以执行计算。 结果将是这样的:

所有代码均可在线获得: calc-monaco-editor

前段时间,我们写了一篇文章,关于在浏览器中使用ANTLR构建简单的Web编辑器 。 我们在下一步的基础上继续进行这项工作,使其适应NPM和WebPack的使用,从而简化了构建应用程序的过程。

为什么要使用摩纳哥?

摩纳哥(Monaco)源自Visual Studio Code(VSCode,为其朋友)。 VSCode是一个轻量级的编辑器,正在吸引越来越多的用户。 摩纳哥基本上将VSCode重新打包以在浏览器中运行。 它是一款出色的编辑器,具有许多有趣的功能,维护得当,并根据许可的开源许可证(MIT许可证)发布。

为什么要使用ANTLR?

ANTLR是一种工具,给定语法可以生成多种目标语言的相应解析器。 除其他外,还支持Java,C#,Python和Javascript。 另一个附加价值是ANTLR有几种语法可用。 因此,如果您学习如何将摩纳哥语和ANTLR结合起来,则可以轻松地在摩纳哥获得对任何可以找到ANTLR语法的语言的支持。 我们提供了有关ANTLR的大量材料,从免费的ANTLR Mega教程到视频课程,以像专业人士一样学习ANTLR

我们的样本项目

让我们修改一下如何组织项目:

  • 在此项目中,我们将使用NPM下载依赖项,例如ANTLR运行时
  • 我们将使用gradle调用ANTLR工具,该工具将从语法定义中为我们的语言生成Javascript解析器
  • 我们将使用TypeScript编写代码。 我们的代码会将ANTLR连接到摩纳哥
  • 我们将使用WebPack将Javascript打包在一个文件中
  • 我们将使用Mocha编写单元测试
  • 我们将使用Kotlin和ktor框架编写一个更简单的服务器。 只要有机会,我就可以选择与Kotlin一起使用,这可以由任何服务器代替。

我们简单的计算语言

我们的语言会非常简单。 它只允许执行非常简单的计算。 这是有意的,但是相同的方法可以用于非常复杂的语言。

我们将能够编写如下代码:

input a
b = a * 2
c = (a - b) / 3
output c

实际上,我们的语言将允许定义:

  • 输入:它们是计算器要接收的值
  • 计算:可以计算新值并将其存储在变量中。 可以从输入或其他变量中计算得出
  • 输出:我们确定要作为计算结果返回的变量

编写解析器

首先,我们将从定义词法分析器和解析器的语法开始。

我们将创建目录src/main/antlr并在该目录中定义文件CalcLexer.g4CalcParser.g4

我们不会从头开始解释如何编写ANTLR语法。 如果您不熟悉ANTLR,则可以从ANTLR Mega Tutorial开始。 但是,我们有一些针对此用例的注释,特别是在词法分析器上。

  1. 我们不应该跳过空格,而应该将这些标记插入特定的频道,因为所有标记都将与语法突出显示相关。
  2. 另外,词法分析器应将每个字符都赋予一个令牌,这就是为什么我们在词法分析器的末尾添加一个特殊规则以捕获任何其他词法分析器规则未捕获的字符的原因。
  3. 为简单起见,我们应避免标记跨越多行或使用词法模式,因为它们会使与摩纳哥的集成更难于语法突出显示。 这些是我们可以解决的问题(我们也可以解决客户的项目),但是我们不想在本教程中解决它们,因为它们会使您更加难以理解基础知识

这是我们的词法分析器语法( CalcLexer.g4 ):

lexer grammar CalcLexer;
channels { WS_CHANNEL }
WS: [ \t]+ -> channel(WS_CHANNEL);
NL: ('\r\n' | '\r' | '\n') -> channel(WS_CHANNEL);
INPUT_KW : 'input' ;
OUTPUT_KW : 'output' ;
NUMBER_LIT : ('0'|[1-9][0-9]*)('.'[0-9]+)?;
ID: [a-zA-Z][a-zA-Z0-9_]* ;
LPAREN : '(' ;
RPAREN : ')' ;
EQUAL : '=' ;
MINUS : '-' ;
PLUS : '+' ;
MUL : '*' ;
DIV : '/' ;
UNRECOGNIZED : . ;

这是我们的解析器语法( CalcParser.g4 ):

parser grammar CalcParser;
options { tokenVocab=CalcLexer; }
compilationUnit:
    (inputs+=input)*
    (calcs+=calc)*
    (outputs+=output)*
    EOF
    ;
input:
   INPUT_KW ID
    ;
output:
    OUTPUT_KW ID
    ;
calc:
   target=ID EQUAL value=expression
   ;
expression:
   NUMBER_LIT
   | ID
   | LPAREN expression RPAREN
   | expression operator=(MUL|DIV) expression
   | expression operator=(MINUS|PLUS) expression
   | MINUS expression
   ;

现在我们有了语法,我们需要从中生成Javascript词法分析器。 为此,我们将需要使用ANTLR工具。 对我而言,最简单的方法是使用gradle下载ANTLR及其依赖项,并在gradle中定义任务以调用ANTLR。

我们将通过运行以下命令安装gradle包装器:

gradle wrapper --gradle-version=5.6.1 --distribution-type=bin

build.gradle脚本将如下所示:

apply plugin: 'java'
repositories {
    jcenter()
}
dependencies {
    runtime 'org.antlr:antlr4:4.7.2'
}
task generateLexer(type:JavaExec) {
  def lexerName = "CalcLexer"
  inputs.file("$ANTLR_SRC/${lexerName}.g4")
  outputs.file("$GEN_JS_SRC/${lexerName}.js")
  outputs.file("$GEN_JS_SRC/${lexerName}.interp")
  outputs.file("$GEN_JS_SRC/${lexerName}.tokens")
  main = 'org.antlr.v4.Tool'
  classpath = sourceSets.main.runtimeClasspath
  args = ['-Dlanguage=JavaScript', "${lexerName}.g4", '-o', '../../main-generated/javascript']
  workingDir = ANTLR_SRC   
}
task generateParser(type:JavaExec) {
  dependsOn generateLexer
  def lexerName = "CalcLexer"
  def parserName = "CalcParser"
  inputs.file("$ANTLR_SRC/${parserName}.g4")
  inputs.file("$GEN_JS_SRC/${lexerName}.tokens")
  outputs.file("$GEN_JS_SRC/${parserName}.js")
  outputs.file("$GEN_JS_SRC/${parserName}.interp")
  outputs.file("$GEN_JS_SRC/${parserName}.tokens")
  main = 'org.antlr.v4.Tool'
  classpath = sourceSets.main.runtimeClasspath
  args = ['-Dlanguage=JavaScript', "${parserName}.g4", '-no-listener', '-no-visitor', '-o', '../../main-generated/javascript']
  workingDir = ANTLR_SRC
}

它使用gradle.properties文件中定义的一些属性:

ANTLR_SRC = src/main/antlr
GEN_JS_SRC = src/main-generated/javascript

实际上,这将使用src/main/antlr下的语法来生成src/main-generated/javascript下的词法分析器。

我们可以运行ANTLR:

./gradlew generateParser

这也将产生词法分析器,作为任务generateParser任务对任务的依赖性generateLexer

运行此命令后,您应该将这些文件放在src/main-generated/javascript

  • CalcLexer.interp
  • CalcLexer.js
  • CalcLexer.tokens
  • CalcParser.interp
  • CalcParser.js
  • CalcParser.tokens

使用NPM管理依赖关系

为了运行我们的词法分析器和解析器,我们需要做两件事:生成的Javascript代码和ANTLR运行时。 为了获得ANTLR运行时,我们将使用NPM。 NPM也将用于下载摩纳哥。 因此,我们不会为项目运行Node.JS,我们只会使用它来获取依赖关系并运行测试。

我们将假定您已经在系统上安装了npm。 如果没有,那么就该打谷歌,弄清楚如何安装它。

安装npm后,我们需要通过填充package.json文件来提供项目配置:

{
  "name": "calc-monaco-editor",
  "version": "0.0.1",
  "author": "Strumenta",
  "license": "Apache-2.0",
  "repository": "https://github.com/Strumenta/calc-monaco-editor",
  "dependencies": {
    "antlr4": "^4.7.2",
    "webpack": "^4.39.2",
    "webpack-cli": "^3.3.7"
  },
  "devDependencies": {
    "mocha": "^6.2.0",
    "monaco-editor": "^0.17.1"
  },
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

idea使用monaco_使用Monaco和ANTLR编写基于浏览器的编辑器 的相关文章

随机推荐

  • 手写模拟Spring的底层原理2.1

    先来引入两个问题 第一个懒加载还是立即加载的问题 这个问题还是在于就是说 当我们xml配置了一个对象bean的时候 它在spring容器里面是什么时候开始会给我们创建这个对象 那如果我们想对某个对象启动懒加载 可以添加 lazy这个注解 这
  • Fiddler抓包工具保姆级使用教程(超详细)

    超文本传输协议 HTTP 是一个简单的请求 响应协议 其主要是基于TCP来实现的 可以通过Chrome开发者工具或者Wireshark或者Fiddler抓包 以便分析 HTTP 请求 响应的细节 本篇博客主要谈论如何使用Fiddler抓取H
  • vector 二维数组

    动态数组 int p p new int m 注意 int m 表示一个有m个元素的指针数组 p new int 8 表示分配一个int空间并初始化为8 for int i 0 i lt m i p i new int 5 利用Vector
  • OpenGL Shading language学习总结

    这篇文章是根据
  • 基于Ymodem协议的STM32串口IAP的实现(IAP + APP + 上位机)

    基于Ymodem协议的STM32串口IAP的实现 IAP APP 上位机 HavenXie关注 0 1832017 06 05 00 35 09字数 1 373阅读 10 038 1 什么是IAP IAP In Application Pr
  • 单元测试Mock工具TestableMock使用

    单元测试原则 单元测试必须遵循AIR Automatic Independent Repeatable 原则 单元测试在线上运行时 感觉像空气 AIR 一样感觉不到 但在测试质量的保障上 却是非常关键的 好的单元测试宏观上来说 具有自动化
  • 计算机网络--数据链路层(1)

    一 数据链路层的功能 数据链路的建立 维护与拆除帧包装 帧传输 帧同步帧的差错恢复 流量控制 MAC地址 也叫做物理地址或者硬件地址 是唯一的 只有支持tcp ip协议的才有 二 交换机的工作原理 1 交换机里有mac地址表 记录哪台电脑接
  • C++中STL库

    六个部分组成 容器 用来存放数据的各种数据结构 比如vector deque list set和map等 是一种类模板 算法 各种常用的算法 比如排序算法 拷贝算法 查找算法等 是一种函数模板 迭代器 容器与算法间的粘合剂 共有五种类型 重
  • 7、oracle随机uuid字符串生成函数

    1 应用场景 数据库表中的id字段一般都是通过uuid自动生成的唯一标识 通过后台代码可以生成uuid然后给id赋值 但是有时候我们不是通过后台代码而是需要通过insert select语句来向表中插入数据 也就是说没有后台代码给生成现成的
  • Topaz Video Enhance AI v3.2.8

    软件介绍 Topaz Video Enhance AI是一款运用了AI人工智能技术的视频放大工具 使用神经网络进行训练的 该神经网络分析成千上万对视频 以了解通常如何丢失细节 够推断出更多细节 从而在单个视频剪辑中提供大量信息的情况下呈现出
  • 达梦数据库-日期类型常用函数汇总

    日期时间函数的参数至少有一个是日期时间类型 TIME DATE TIMESTAMP 返回值一般为日期时间类型和数值类型 由于 DM 支持儒略历 并考虑了历史上从儒略历转换至格里高利日期时的异常 不计算 1582 10 05 到 1582 1
  • MATLAB:excel文件读取

    1 用xlsread函数读取一个Excel文件 1 num xlsread filename filename是单引号括起来的带路径的文件名 函数直接读取filename所指文件的sheet1中的数据区域存储到双精度矩阵num中 其中 数据
  • RIP的缺点

    1收敛慢2路由选取到无限3不能处理VLSM 版本14不能检测路由环路5度量值只是跳跃计数6网络直径小 15个跳跃 转载于 https www cnblogs com bbbbnn p 10914421 html
  • 初识决策树(Decision Tree)

    今天来看一下西瓜书第四章 决策树 文章目录 信息增益 增益率 基尼系数 剪枝处理 预剪枝 后剪枝 连续值与缺失值处理 连续值处理 缺失值处理 决策树 简单来说就是一个树形结构从根节点往叶子节点进行决策 树内部的每一个节点是对一个特征的测试
  • Wireshark和TcpDump抓包分析心得

    Wireshark和TcpDump抓包分析心得 分类 Network2010 12 14 20 19 3242人阅读 评论 5 收藏 举报 1 Wireshark与tcpdump介绍 Wireshark是一个网络协议检测工具 支持Windo
  • 二次封装element-ui table,操作列手动传入按钮

    我们在使用element ui时 必定会用到表格这个组件 虽然element组件已经为我们封装很好了 但是我们在实际开发中会根据我们的业务在element ui的基础上再次封装 比如表格最后一列会经常有操作这一列 对应着不同的按钮 像编辑按
  • Java注解(Java高级)

    思维导图 1 注解概述 什么是注解 什么是注解 Annotation 注解 是一种代码级别的说明 它是 JDK1 5 及以后版本引入的一个特性 与类 接口 枚举是在同一个层次 注解的作用 主要用于取代 XML 和 properties 配置
  • JAVA多线程中数据一致性的问题

    多线程中数据一致性的问题 说到一致性 除了在并发编程中保证共享变量数据的一致性之外 还有数据库的 ACID 中的 C Consistency 一致性 分布式系统的 CAP 理论中的 C Consistency 一致性 并发编程是一种重要的程
  • 切换svn服务器的时候,老是链接不成功

    附 svn下载地址 http download csdn net detail u012744024 7867979 http pan baidu com s 1qWv35yk 浪费了我多半个晚上 一个上午的时间 害的我重新装了一个svn
  • idea使用monaco_使用Monaco和ANTLR编写基于浏览器的编辑器

    idea使用monaco 这是关于为我们将要定义的新语言创建基于浏览器的编辑器的教程 我们将使用两个组件 Monaco 它是一个很棒的基于浏览器的编辑器 或一个Web编辑器 如您所愿 ANTLR 这是我们喜欢用来构建各种解析器的解析器生成器