java实现snl语法分析_使用antlr4及java实现snl语言的解释器
其实我对于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语言的解释器相关推荐
- java list e 查找_源码(04) -- java.util.ListE
java.util.List 源码分析(JDK1.7) ------------------------------------------------------------------------ ...
- java 基础 笔试题_非常全面的java基础笔试题
1.下列说法正确的是() (程序结构) A java程序的main方法必须写在类甩面 B java程序中可以有多个main方法 C.java程序中类名必须与文件名一样 D.JAVA程序的main方法中 ...
- 李兴华java视频在线观看_李兴华Java开发实战经典视频教程_IT教程网
资源名称:李兴华Java开发实战经典视频教程 资源目录: [IT教程网]010201_[第2章:简单Java程序]_简单Java程序 [IT教程网]010301_[第3章:Java基础程序设计]_Ja ...
- 李兴华java实战经典视频_李兴华Java开发实战经典视频教程
资源名称:李兴华Java开发实战经典视频教程 资源目录:[一品资源网]010201_[第2章:简单Java程序]_简单Java程序[一品资源网]010301_[第3章:Java基础程序设计]_Java ...
- java中char类型_【考点】JAVA中的char类型
写在前面: 本周,在我们同学的刷题群里,一位同学上传了一道关于char的题,引起的不少同学的热议.热议的同时,我们也发现近乎一半的同学对char的基础知识一知半解,今天我们给大家一个浅显易懂的解释,赶 ...
- 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 ...
- java下拉菜单_薪资对比:Java开发和web前端薪资哪个好
Web前端开发和Java开发哪个薪资更高,Web前端开发和Java开发发展前景更好? 互联网行业飞速发展,因此有很多小伙伴想要进入IT行业分一杯羹,但是学什么技术更好,哪一个语言的就业薪资更高,就成了 ...
- java为什么被开发者_为什么开发者对Java 9如此的兴奋
随着标准 Java 的版本更新,开发者总是可以从升级后的版本中获取想要的功能.那么 Java 9 的发布为什么会让开发者如此的兴奋?下面列出了一些主要原因: 1.模块化的源代码 JDK 源代码将以模块 ...
- java主要内存区域_可能是把Java内存区域讲的最清楚的一篇文章
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 介绍下 Java 内存区域(运行时数据区) Java 对象的创建过程(五步,建议能默写出来并且要知道每一步虚拟机做了什么) 对象的访问定位的两种方式(句柄 ...
最新文章
- 实战1--应用EL表达式访问JavaBean的属性
- python 脚本学习(二)
- design php 如何使用ant_Ant Design Pro初探—添加面包屑
- 有两个python怎么停用其中一_如何在python中停止另一个已经运行的脚本?
- spring中使用scala的maven打包配置
- python从大到小排序_python作业:用嵌套的列表存储学生成绩数据,并编程完成如下操作...
- openresty入门 方法及指令
- 写给我们奔三的80后们……
- 17 java 存在的问题(转)
- android开机动画多长时间_Android开机动画及黑屏
- 2021年全球及中国AMOLED行业发展现状、竞争格局及未来发展趋势分析,柔性AMOLED面板将占领市场「图」
- CentOS7.6安装MySQL5.7
- 似然比和p值不同的原因_二代P值:传统P值的升级 | 社论前沿
- 戴尔笔记本电脑PIN码忘了, 怎么办
- 浅析部分物化以及冰山立方体的计算方法Star-Cubing
- Altium Designer——常见贴片钽电容封装尺寸及特性
- DirectX函数总结2
- MTK平台产线生产标记位功能
- FOC学习之路——硬件电路(一)
- Arduino从零开始学习(一)
热门文章
- Python--安装pyecharts包,anaconda环境下如何正确安装神奇可视化pyecharts包[安装的那些事儿]
- raid 0 raid1 raid5 raid10(0+1)的区别
- 回归分析结果表格怎么填_Excel回归分析结果的详细阐释
- Linux-hosts
- 三星 android 5.0 root,三星N9008S Android 5.0 (GALAXY Note 3 移动4G)ROOT教程,简单几步完成ROOT...
- 惠普高性能计算服务器,高密度计算 惠普SL2500系列服务器推荐
- 妮妮lisp_贡献卓越 device首次荣获Major赛事MVP
- 在surface go 2上安装ubuntu 20.04
- Jlink使用技巧之虚拟串口功能
- 什么是服务器信息,什么是服务器地址信息