这是该系列的第一篇文章。 本系列的目的是描述如何创建有用的语言和所有支持工具。

在本文中,我们将开始研究一种非常简单的表达语言。 我们将在语言沙箱中构建它,因此我们将其称为语言Sandy

我认为工具支持对于一种语言至关重要:因此,我们将从一种非常简单的语言开始,但是我们将为此提供丰富的工具支持。 要从一种语言中受益,我们需要解析器,解释器和编译器,编辑器等。 在我看来,构建简单的解析器的材料很多,但是构建使用语言的实用有效所需的其余基础结构的材料却很少。

我想专注于这些方面,使语言小巧但完全有用。 然后,您将能够有机地增长语言。

该代码可在GitHub上找到: https : //github.com/ftomassetti/LangSandbox 。 本文中提供的代码对应于标记01_lexer。

语言

该语言将允许定义变量和表达式。 我们将支持:

  • 整数和十进制文字
  • 变量定义和赋值
  • 基本数学运算(加法,减法,乘法,除法)
  • 括号的用法

有效文件的示例:

var a = 10 / 3
var b = (5 + 3) * 2
var c = a / b

我们将使用的工具

我们将使用:

  • ANTLR生成词法分析器和解析器
  • 使用Gradle作为我们的构建系统
  • 用Kotlin编写代码。 鉴于我刚开始学习,这将是非常基本的Kotlin。

设置项目

我们的构建。 gradle文件将如下所示

buildscript {ext.kotlin_version = '1.0.3'repositories {mavenCentral()maven {name 'JFrog OSS snapshot repo'url  'https://oss.jfrog.org/oss-snapshot-local/'}jcenter()}dependencies {classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"}
}apply plugin: 'kotlin'
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'antlr'repositories {mavenLocal()mavenCentral()jcenter()
}dependencies {antlr "org.antlr:antlr4:4.5.1"compile "org.antlr:antlr4-runtime:4.5.1"compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"testCompile 'junit:junit:4.12'
}generateGrammarSource {maxHeapSize = "64m"arguments += ['-package', 'me.tomassetti.langsandbox']outputDirectory = new File("generated-src/antlr/main/me/tomassetti/langsandbox".toString())
}
compileJava.dependsOn generateGrammarSource
sourceSets {generated {java.srcDir 'generated-src/antlr/main/'}
}
compileJava.source sourceSets.generated.java, sourceSets.main.javaclean{delete "generated-src"
}idea {module {sourceDirs += file("generated-src/antlr/main")}
}

我们可以运行:

  • ./gradlew想法来生成IDEA项目文件
  • ./gradlew generateGrammarSource生成ANTLR词法分析器和解析器

实施词法分析器

我们将在两个单独的文件中构建词法分析器和解析器。 这是词法分析器:

lexer grammar SandyLexer;// Whitespace
NEWLINE            : '\r\n' | 'r' | '\n' ;
WS                 : [\t ]+ ;// Keywords
VAR                : 'var' ;// Literals
INTLIT             : '0'|[1-9][0-9]* ;
DECLIT             : '0'|[1-9][0-9]* '.' [0-9]+ ;// Operators
PLUS               : '+' ;
MINUS              : '-' ;
ASTERISK           : '*' ;
DIVISION           : '/' ;
ASSIGN             : '=' ;
LPAREN             : '(' ;
RPAREN             : ')' ;// Identifiers
ID                 : [_]*[a-z][A-Za-z0-9_]* ;

现在,我们可以简单地运行./ gradlew generateGrammarSource ,然后将根据先前的定义为我们生成词法分析器。

测试词法分析器

测试始终很重要,但是在构建语言时绝对至关重要:如果支持您的语言的工具不正确,这可能会影响您将为其构建的所有程序。 因此,让我们开始测试词法分析器:我们只需要验证词法分析器产生的标记序列就是我们所关注的。

package me.tomassetti.sandyimport me.tomassetti.langsandbox.SandyLexer
import org.antlr.v4.runtime.ANTLRInputStream
import java.io.*
import java.util.*
import org.junit.Test as test
import kotlin.test.*class SandyLexerTest {fun lexerForCode(code: String) = SandyLexer(ANTLRInputStream(StringReader(code)))fun lexerForResource(resourceName: String) = SandyLexer(ANTLRInputStream(this.javaClass.getResourceAsStream("/${resourceName}.sandy")))fun tokens(lexer: SandyLexer): List<String> {val tokens = LinkedList<String>()do {val t = lexer.nextToken()when (t.type) {-1 -> tokens.add("EOF")else -> if (t.type != SandyLexer.WS) tokens.add(lexer.ruleNames[t.type - 1])}} while (t.type != -1)return tokens}@test fun parseVarDeclarationAssignedAnIntegerLiteral() {assertEquals(listOf("VAR", "ID", "ASSIGN", "INTLIT", "EOF"),tokens(lexerForCode("var a = 1")))}@test fun parseVarDeclarationAssignedADecimalLiteral() {assertEquals(listOf("VAR", "ID", "ASSIGN", "DECLIT", "EOF"),tokens(lexerForCode("var a = 1.23")))}@test fun parseVarDeclarationAssignedASum() {assertEquals(listOf("VAR", "ID", "ASSIGN", "INTLIT", "PLUS", "INTLIT", "EOF"),tokens(lexerForCode("var a = 1 + 2")))}@test fun parseMathematicalExpression() {assertEquals(listOf("INTLIT", "PLUS", "ID", "ASTERISK", "INTLIT", "DIVISION", "INTLIT", "MINUS", "INTLIT", "EOF"),tokens(lexerForCode("1 + a * 3 / 4 - 5")))}@test fun parseMathematicalExpressionWithParenthesis() {assertEquals(listOf("INTLIT", "PLUS", "LPAREN", "ID", "ASTERISK", "INTLIT", "RPAREN", "MINUS", "DECLIT", "EOF"),tokens(lexerForCode("1 + (a * 3) - 5.12")))}
}

结论和下一步

我们从第一步开始:设置项目并构建词法分析器。

使这种语言在实践中可用之前,我们还有很长的路要走,但是我们开始了。 接下来,我们将使用相同的方法来处理解析器:构建一些简单的东西,以便我们可以通过命令行进行测试和编译。

翻译自: https://www.javacodegeeks.com/2016/07/getting-started-antlr-building-simple-expression-language.html

ANTLR入门:构建一种简单的表达语言相关推荐

  1. antlr idea 入门_ANTLR入门:构建简单的表达语言

    antlr idea 入门 这是该系列的第一篇文章. 本系列的目的是描述如何创建有用的语言和所有支持工具. 在本文中,我们将开始研究一种非常简单的表达语言. 我们将在语言沙箱中构建它,因此我们将其称为 ...

  2. 密码学入门:几种简单的密码

    密码学入门:几种简单的密码 一.维吉尼亚密码       维吉尼亚密码引入了"密钥"的概念,即根据密钥来决定用哪一行的密表来进行替换,以此来对抗字频统计.假如以上面第一行代表明文字 ...

  3. java语言编写简易表达式_将简单的表达语言放入Java

    小编典典 您可以看到如何传递所有参数: ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = m ...

  4. 分布式锁简单入门以及三种实现方式介绍_徐刘根的博客-CSDN博客

    原文地址 rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmled ...

  5. 分布式锁简单入门以及三种实现方式介绍(滴滴)

    很多小伙伴在学习Java的时候,总是感觉Java多线程在实际的业务中很少使用,以至于不会花太多的时间去学习,技术债不断累积!等到了一定程度的时候对于与Java多线程相关的东西就很难理解,今天需要探讨的 ...

  6. 分布式锁简单入门以及三种实现方式介绍

    分布式锁简单入门以及三种实现方式介绍 2018年01月11日 21:16:28 徐刘根 阅读数:37912 标签: 分布式 分布式锁 高并发 更多 个人分类: 集群分布式 版权声明:本文为博主原创文章 ...

  7. linux入门_Linux入门的10种方法

    linux入门 文章什么是Linux用户? 作者:安德森·席尔瓦(Anderson Silva)明确指出,如今,只要您对"使用Linux"的定义足够广泛,人们使用Linux(以某种 ...

  8. UI设计入门:五种基本APP界面类型【萧蕊冰】

    今天这篇是一个UI设计入门:五种基本APP界面类型的欣赏.随着互联网的发展和智能手机的普及,移动应用成了大家最热爱的宠儿,许多移动APP也会根据用户的需求来随时替换本身的UI设计.本篇UI设计入门分享 ...

  9. (论文精读)PCANet:一种简单的图像分类的深度学习基线

    PCANet:一种简单的图像分类的深度学习基线 \quad\quad这篇文章主要对论文<PCANet: A Simple Deep Learning Baseline forImage Clas ...

最新文章

  1. python语言是由谁设计并领导开发的_python语言概述 - osc_lt3ocv4d的个人空间 - OSCHINA - 中文开源技术交流社区...
  2. oracle 10g的进程主要分为,Oracle10g 后台进程列表
  3. 饶军:Apache Kafka的过去,现在,和未来 1
  4. Ubuntu把家目录文件夹名称改为英文
  5. 深度 | 从各种注意力机制窥探深度学习在NLP中的神威
  6. 《设计模式之美》课程笔记之DDD开发实战
  7. 力特usb转232驱动程序下载_电脑USB接口、U盘接口不能使用的原因及解决方法
  8. Go语言 for循环案例
  9. (转)wxWindows一些网文
  10. keil教程——串口调试
  11. otf字体转ttf字体
  12. cad中简单流程图制作,带控制点的工艺流程图cad_使用CAD绘制工艺流程图的方法步骤详解...
  13. 在线画图工具,高效办公
  14. java程序实现短信发送(可调用免费短信接口)
  15. 嵌入式Linux资源网站,嵌入式Linux名词及资源
  16. 北大核刊最新版2020目录_2021年一建教材出来了?最新版考点速记手册,早备考早通关...
  17. 计算机按音乐视频,电脑怎么提取视频中的音乐
  18. 数学建模 | MATLAB学习 | 插值 一维插值函数、三次样条插值
  19. 我们能从后验分布中学到什么?贝叶斯后验的频率解释
  20. PHP图书管理系统实训心得体会,图书馆信息管理系统——总结

热门文章

  1. 阿里巴巴对Java编程【单元测试】的规约
  2. ssm(Spring+Spring mvc+mybatis)Spring配置文件——applicationContext-servlet.xml
  3. centos7离线安装oracle11g,CentOS 7.5离线安装Oracle 11gR2
  4. php类常量的特点,php类常量是什么?类常量用法详解
  5. matlab边算边出图命令,Matlab:不包含边境和工具栏的figure(移除保存图片的白边)...
  6. 天平游码读数例题_初二上册物理实验——托盘天平使用的注意事项
  7. 可以搜python编程答案的软件_python实现百万答题自动百度搜索答案
  8. jvm 助记符_您的JVM是否泄漏文件描述符-像我的一样?
  9. aws 删除ec2实例_如何在AWS EC2实例上部署Spring Boot应用程序
  10. 忽略异常_忽略已检查的异常,所有出色的开发人员都在这样做–基于600,000个Java项目...