其实我对于antlr4的理解也仅限于那篇文章的范围,但那些内容对于我们实现一个SNL语言已是足够了。

简单说来,这是一个非常简单的结构化编程语言,它包含了一个编程语言应该有的最基本的东西,同时基本上不包含其它的所谓先进的元素。

首先贴一下文法(我对原始的文法做了一些调整,如:原始的文法中if语句的else部分不是可选的,原始文法中record类型内部只能有基础类型或array类型,等等。但我所做的这些调整都是比较边缘的,以下文法基本上保持了SNL语言的原貌):

grammar Snlc;

@header{package net.yeah.zhouyou.mickey.snl.antlr4;}

program: programHead declarePart programBody? ;

programHead: PROGRAM programName=ID ;

declarePart: typeDecpart? varDecpart? procDecpart? ;

typeDecpart: TYPE typeDecList ;

typeDecList: typeId=ID ':=' typeDef ';' typeDecList? ;

typeDef: basicType

| structureType

| ID

;

basicType: INTEGER | CHAR ;

structureType: arrayType

| recordType

;

arrayType: ARRAY '[' low=INTC '..' top=INTC ']' OF basicType ;

recordType: RECORD fieldDecList END ;

fieldDecList: typeDef idList ';' fieldDecList? ;

idList: ID (',' idList)? ;

varDecpart: VAR varDecList ;

varDecList: typeDef idList ';' varDecList? ;

procDecpart: procDeclare procDecpart? ;

procDeclare: PROCEDURE procName=ID '(' paramList? ')' ';'

declarePart programBody ;

paramList: param (';' paramList)? ;

param: VAR? typeDef idList ;

programBody: BEGIN stmList END ;

stmList: stm (';' stmList)? ;

stm: conditionalStm

| loopStm

| inputStm

| outputStm

| assignment

| callStm

| RETURN

;

assignment: variable ':=' exp ;

callStm: ID '(' actParamList? ')' ;

conditionalStm: IF condExp THEN stmList (ELSE stmList)? FI ;

loopStm: WHILE condExp DO stmList ENDWH ;

inputStm: READ '(' invar=ID ')' ;

outputStm: WRITE '(' exp ')' ;

actParamList: exp (',' actParamList)? ;

condExp: exp (cmpOp=(EQ | LT) exp)? ;

exp: exp op=(MUL | DIV) exp

| exp op=(ADD | SUB) exp

| factor

;

factor: '(' exp ')'

| intVal=INTC

| variable

;

variable: ID variMore? ;

variMore: '[' exp ']'

| DOT ID variMore?

;

//

PROGRAM: 'program' ;

TYPE: 'type';

INTEGER: 'integer' ;

CHAR: 'char' ;

ARRAY: 'array' ;

OF: 'of' ;

RECORD: 'record' ;

BEGIN: 'begin' ;

END: 'end' ;

PROCEDURE: 'procedure' ;

VAR: 'var' ;

IF: 'if' ;

THEN: 'then' ;

ELSE: 'else' ;

WHILE: 'while' ;

DO: 'do';

ENDWH: 'endwh' ;

READ: 'read' ;

WRITE: 'write' ;

RETURN: 'return' ;

FI: 'fi' ;

ID: [a-zA-Z][a-zA-Z0-9]* ;

INTC: [0-9]+ ;

ADD: '+' ;

SUB: '-' ;

MUL: '*' ;

DIV: '/' ;

EQ: '=' ;

LT: '

DOT: '.' ;

DDOT: '..' ;

AMGT: ':=' ;

SEM: ';' ;

COMMA: ',' ;

LBT: '(' ;

RBT: ')' ;

LSBT: '[' ;

RSBT: ']' ;

WS: [ \t\n\r]+ -> skip;

读懂这个文法就完全清楚了这门语言的语法结构了,大家可以直接用它来开始开发了,对于语义的部分,大家猜都能猜得出个大概。

但是文法对于学习一个语言来说是比较抽象的,虽然大家都能看懂,但过于理论化,所以我写几个例子贴在下面。

例一,以下程序演示了参数传递,调用proc时传入三个参数1,2,3,在proc内部打印这三个参数的值到控制台——如果我们实现的没有问题,则它应该可以正确打印出这三个数字:

program test

procedure proc(integer a, b; integer c);

begin

write(a);

write(b);

write(c)

end

begin

proc(1, 2, 3)

end

例二,以下程序中创建了一个整数数组,这个数组的下标是从6到8,共三个值(或三个引用),然后分写或读数组的每个元素。

program test

var array[6..8] of integer a;

begin

a[6] := 1;

a[7] := 2;

a[8] := 3;

write(a[6]);

write(a[7]);

write(a[8])

end

例三,以下程序定义了一个过程f,当调用这个过程中,会打印当前的参数,并把参数+1传入下一次的递归调用中。如果没有实现“尾递归优化”,则这个程序的调用可预期的情况是“堆栈溢出”。

program recursion

procedure f(integer d);

begin

write(d);

f(d + 1)

end

begin

f(1)

end

例四,以下程序用来表示引用传参。我们把t做为参数传到ref过程中,过程中对参数n做了一些动作,结束这个过程后打印t——如果我们的实现中,把实参t传给形参n是值传递的,则最终会打印出5(因为过程内部无论做了什么都改变不了实参);如果我们的实现中,把实参t传给形参n是引用传递的,则n和t在语义上就是同一个对象,则作用于n的都会在t上有所体现。

在我的实现中,它会打印出3,因为我把参数传递实现为引用传递,但把 := 实现为值传递。

program test

var integer t;

procedure ref(integer n);

var integer i;

begin

i := n;

n := 3;

i := 1

end

begin

t := 5;

ref(t);

write(t)

end

例五,以下程序中的factorial过程用于计算n的阶乘,因为我实现的是引用传参,所以我们可以用参数从过程中返回结果。如果我们不设计成引用传参,则需要使用全局变量来传递数据了。

program test

var integer res;

procedure factorial(integer n, r);

begin

r := 1;

factorial_recursion(n, r)

end

procedure factorial_recursion(integer n, r);

begin

if 1 < n then

r := r * n;

factorial_recursion(n - 1, r)

fi

end

begin

factorial(10, res);

write(res)

end

例六,以下程序用来测试类型定义的功能(其实是一个挺无聊的测试用例)

program test

type

int := integer;

array1to20 := array[1..20] of char;

recordtype1 := record

int a, b;

array1to20 c;

end;

recordtype2 := record

recordtype1 v;

char c;

end;

var recordtype2 v;

array1to20 v2;

begin

v.v.a := 1;

write(v.v.a);

v2[1] := 65;

write(v2[1]);

v.v.c[1] := 68;

write(v.v.c[1]);

v.c := 66;

write(v.c)

end

例七,以下程序实现了一个冒泡排序(这是教材上给出的例子):

program bubble

var integer i, j, num;

array [1..20] of integer a;

procedure q(integer num);

var integer i, j, k;

integer t;

begin

i := 1;

while i < num do

j := num - i + 1;

k := 1;

while k < j do

if a[k + 1] < a[k] then

t := a[k];

a[k] := a[k + 1];

a[k + 1] := t

else

t := 0

fi;

k := k + 1

endwh;

i:= i + 1

endwh

end

begin

read(num);

i := 1;

while i < (num + 1) do

read(j);

a[i] := j;

i := i + 1

endwh;

q(num);

i := 1;

while i < (num + 1) do

write(a[i]);

i := i + 1

endwh

end.

经过以上的介绍,大家应该对SNL这个语言比较理解了,下面我选择这个解释器最重要的部分介绍一下开发思路。

一、堆栈

………………

二、上下文(符号表)

………………

三、引用

………………

四、类型

………………

java实现snl语法分析_使用antlr4及java实现snl语言的解释器相关推荐

  1. java list e 查找_源码(04) -- java.util.ListE

    java.util.List 源码分析(JDK1.7) ------------------------------------------------------------------------ ...

  2. java 基础 笔试题_非常全面的java基础笔试题

    1.下列说法正确的是() (程序结构) A java程序的main方法必须写在类甩面 B java程序中可以有多个main方法 C.java程序中类名必须与文件名一样 D.JAVA程序的main方法中 ...

  3. 李兴华java视频在线观看_李兴华Java开发实战经典视频教程_IT教程网

    资源名称:李兴华Java开发实战经典视频教程 资源目录: [IT教程网]010201_[第2章:简单Java程序]_简单Java程序 [IT教程网]010301_[第3章:Java基础程序设计]_Ja ...

  4. 李兴华java实战经典视频_李兴华Java开发实战经典视频教程

    资源名称:李兴华Java开发实战经典视频教程 资源目录:[一品资源网]010201_[第2章:简单Java程序]_简单Java程序[一品资源网]010301_[第3章:Java基础程序设计]_Java ...

  5. java中char类型_【考点】JAVA中的char类型

    写在前面: 本周,在我们同学的刷题群里,一位同学上传了一道关于char的题,引起的不少同学的热议.热议的同时,我们也发现近乎一半的同学对char的基础知识一知半解,今天我们给大家一个浅显易懂的解释,赶 ...

  6. java面试32问_学员分享:JAVA面试32问(11-20)

    第十一,short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错? short s1 = 1; s1 = s1 + 1;有错,s1是shor ...

  7. java下拉菜单_薪资对比:Java开发和web前端薪资哪个好

    Web前端开发和Java开发哪个薪资更高,Web前端开发和Java开发发展前景更好? 互联网行业飞速发展,因此有很多小伙伴想要进入IT行业分一杯羹,但是学什么技术更好,哪一个语言的就业薪资更高,就成了 ...

  8. java为什么被开发者_为什么开发者对Java 9如此的兴奋

    随着标准 Java 的版本更新,开发者总是可以从升级后的版本中获取想要的功能.那么 Java 9 的发布为什么会让开发者如此的兴奋?下面列出了一些主要原因: 1.模块化的源代码 JDK 源代码将以模块 ...

  9. java主要内存区域_可能是把Java内存区域讲的最清楚的一篇文章

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 介绍下 Java 内存区域(运行时数据区) Java 对象的创建过程(五步,建议能默写出来并且要知道每一步虚拟机做了什么) 对象的访问定位的两种方式(句柄 ...

最新文章

  1. centos7安装mongodb详解
  2. 大小端判断和网络字节序
  3. js滚动页面到固定位置进行操作
  4. 使用模板将Web服务的结果转换为标记语言
  5. python移除链表元素
  6. ASP.NET的Page.IsPostBack 属性详细说明(转)
  7. Oracle中的in 和 not in
  8. LeetCode题 - 13 罗马数字转整数
  9. 动态规划问题以及诸多实例分析
  10. sqlserver openrowset mysql_sqlserver连接mysql
  11. 很恶心的一个关于字符串的题目!
  12. oracle 多实例 端口,Oracle一个实例配置多个listener或多个端口
  13. c语言用switch做一个计算器,求助。。关于用switch编写简易计算器
  14. 读书笔记:高等代数 上册
  15. Android截屏工具类的使用
  16. 全球顶尖互联网公司谷歌都在使用的Mono-Repo单体仓库
  17. Python的Profile概述
  18. VMware虚拟机中安装苹果系统MacOS 10.12 Sierra
  19. 【Java字符串分割[split()]和截取[substring()]】
  20. 计算机综合训练50题4,-计算机基础练习题-Excel部分50题.doc

热门文章

  1. Import Error: from torchtext.data import to_map_style_dataset解决方案
  2. Inherits、CodeFile、CodeBehind的意义
  3. h5 audio播放音频文件
  4. Solr语法解析及SolrJ使用
  5. catkin_make, cmake, catkin build区别
  6. Vue实战篇二十六:创建动态仪表盘
  7. 从构造函数看线程安全
  8. Ubuntu重启后不显示共享文件夹
  9. 康熙的儿子们和他们的结局
  10. word数字批量转为会计计数