实现自己的脚本语言ngscript之三:语法设计
这是第四篇了,之所以隔了这么久才写,一方面是因为最近开始实习了,另一方面是因为设计语法真是要考虑很多东西。
于是我去读了这本书,里面实现了两种语言,一种跟js差不多语法,用ast解释执行;另一种语法类似java,编译成字节码执行。
于是ngscript就愉快的决定使用类似js语法、编译成字节码了。
这之间还看了一本《flex与bison》,主要看了看LALR(1)中冲突的处理和写文法要注意的事情。
现在的BNF已经写成这个样子了。可能还会不断的改。常用的控制结构和try…catch都有。
//starter symbol
%start <program>;
%array <statements> <param_list> <params>;
%equiv <expr> <expr1> <expr2> <expr3> <expr4> <expr5> <expr6> <expr7> <expr8> <nullable_expr>;
%filter semicolon comma; <program> ::= <statements>; //----------------------------------------------------------------------------
//statements is a collection of statement; <statements> ::= NULL;
<statements> ::= <statement> <statements>; //----------------------------------------------------------------------------
//statement forms
%equiv <statement> <flow_statement> <expr_statement> <fc_statement>; <statement> ::= <flow_statement>;
<statement> ::= <expr_statement>;
<statement> ::= <fc_statement>;
<statement> ::= <throw_exception>; <flow_statement> ::= <function_decl>;
<flow_statement> ::= <if_block>;
<flow_statement> ::= <for_block>;
<flow_statement> ::= <if_else_block>;
<flow_statement> ::= <while_block>;
<flow_statement> ::= <try_block>;
<flow_statement> ::= <switch_block>; <expr_statement> ::= <expr> semicolon;
<throw_exception> ::= throw <expr> semicolon => <expr>; <fc_statement> ::= <return_val>;
<fc_statement> ::= <return_void>;
<fc_statement> ::= break semicolon;
<fc_statement> ::= continue semicolon; <return_val> ::= return <expr> semicolon => <expr>;
<return_void> ::= return semicolon; //error handling
//<statement> ::= ERROR semicolon; //----------------------------------------------------------------------------
//details of function declaration <function_decl> ::= function ident lparen <param_list> rparen lcurly <statements> rcurly
=> ident <param_list> <statements>;
<param_list> ::= ident comma <param_list>;
<param_list> ::= ident;
<param_list> ::= NULL;
//----------------------------------------------------------------------------
//details of if block and else <if_block> ::= if lparen <expr> rparen lcurly <statements> rcurly
=> <expr> <statements> ;
<if_else_block> ::= if lparen <expr> rparen lcurly <statements> rcurly else lcurly <statements> rcurly
=> <expr> <statements> <statements>; //----------------------------------------------------------------------------
//details of expr <expr> ::= <expr> assign <expr1> => assign <expr> <expr1>;
<expr> ::= <expr> sub_assign <expr1> => sub_assign <expr> <expr1>;
<expr> ::= <expr1>; <expr1> ::= <expr1> or <expr2> => or <expr1> <expr2>;
<expr1> ::= <expr2>; <expr2> ::= <expr2> and <expr3> => and <expr2> <expr3>;
<expr2> ::= <expr3>; <expr3> ::= <expr3> eq <expr4> => eq <expr3> <expr4>;
<expr3> ::= <expr3> neq <expr4> => neq <expr3> <expr4>;
<expr3> ::= <expr4>; <expr4> ::= <expr4> gt <expr5> => gt <expr4> <expr5>;
<expr4> ::= <expr4> lt <expr5> => lt <expr4> <expr5>;
<expr4> ::= <expr4> ge <expr5> => ge <expr4> <expr5>;
<expr4> ::= <expr4> le <expr5> => le <expr4> <expr5>;
<expr4> ::= <expr5>; <expr5> ::= <expr5> add <expr6> => add <expr5> <expr6>;
<expr5> ::= <expr5> sub <expr6> => sub <expr5> <expr6>;
<expr5> ::= <expr6>; <expr6> ::= <expr6> mul <expr7> => mul <expr6> <expr7>;
<expr6> ::= <expr6> div <expr7> => div <expr6> <expr7>;
<expr6> ::= <expr6> mod <expr7> => mod <expr6> <expr7>;
<expr6> ::= <expr7>; <expr7> ::= not <expr8>;
<expr7> ::= s_minus <expr8>;
<expr7> ::= inc <expr8>;
<expr7> ::= dec <expr8>;
<expr7> ::= typeof <expr8>;
<expr7> ::= new <expr8> lparen <params> rparen => new <expr8> <params>;
<expr7> ::= <expr8>; <expr8> ::= <expr8> dot ident => dot <expr8> ident;
<expr8> ::= lparen <expr> rparen => <expr>;
<expr8> ::= <expr8> lsqr <expr> rsqr => array <expr8> <expr>;
<expr8> ::= <expr8> lparen <params> rparen => funcall <expr8> <params>;
<params> ::= <expr> comma <params>;
<params> ::= <expr> ;
<params> ::= NULL; <expr8> ::= lcurly <params> rcurly;
<expr8> ::= float;
<expr8> ::= ident;
<expr8> ::= integer;
<expr8> ::= string;
<expr8> ::= function lparen <param_list> rparen lcurly <statements> rcurly
=> lambda <param_list> <statements>; <for_block> ::= for lparen <nullable_expr> semicolon <nullable_expr> semicolon <nullable_expr> rparen lcurly <statements> rcurly
=> <nullable_expr> <nullable_expr> <nullable_expr> <statements>; <nullable_expr> ::= <expr>;
<nullable_expr> ::= NULL; <while_block> ::= while lparen <expr> rparen lcurly <statements> rcurly
=> <expr> <statements>; <try_block> ::= try lcurly <hooked_statements> rcurly catch lparen ident rparen
lcurly <hooked_statements> rcurly finally lcurly <statements> rcurly
=> <hooked_statements> ident <hooked_statements> <statements>; %equiv <statements> <hooked_statements>; <hooked_statements> ::= <hooked_statement> <hooked_statements>;
<hooked_statements> ::= NULL; %equiv <statement> <hooked_statement> <hooked_fc_statement>; <hooked_statement> ::= <flow_statement>;
<hooked_statement> ::= <expr_statement>;
<hooked_statement> ::= <hooked_fc_statement>;
<hooked_statement> ::= <throw_exception>; <hooked_fc_statement> ::= <hooked_return_val>;
<hooked_fc_statement> ::= <hooked_return_void>;
<hooked_fc_statement> ::= <hooked_break>;
<hooked_fc_statement> ::= <hooked_continue>; <hooked_return_val> ::= return <expr> semicolon => <expr>;
<hooked_return_void> ::= return semicolon;
<hooked_break> ::= break semicolon;
<hooked_continue> ::= continue semicolon; <switch_block> ::= switch lparen <expr> rparen lcurly <switch_cases> <default_case> rcurly
=> <expr> <switch_cases> <default_case>; <switch_block> ::= switch lparen <expr> rparen lcurly <switch_cases> rcurly
=> <expr> <switch_cases>; %array <switch_cases>; <switch_cases> ::= <switch_case> <switch_cases>;
<switch_cases> ::= NULL; <switch_case> ::= case <expr> colon <statements>
=> <expr> <statements>;
<default_case> ::= default colon <statements>
=> <statements>;
parseroid加上这个描述,就可以分析出ngscript程序的语法树。大概是这个样子

生成树之后就是编译成字节码了,这个会在下一篇中详述。
实现自己的脚本语言ngscript之三:语法设计的更多相关文章
- 关于JS脚本语言的基础语法
JS脚本语言的基础语法:输出语法 alert("警告!"); confirm("确定吗?"); prompt("请输入密码");为弱 ...
- Cocos2d-x 脚本语言Lua基本语法
Cocos2d-x 脚本语言Lua基本语法 前面一篇博客对Lua这门小巧的语言进行了简单的介绍.本篇博客来给大家略微讲一下Lua的语法.不会长篇累牍得把Lua的全部语法都讲一遍,这里通过下面几点来讲L ...
- 实现自己的脚本语言ngscript之零
正式开始介绍前先扯点没用的. 从小玩basic长大的小朋友大多有一个梦想,就是自己实现一个basic解释器. 不过这里我实现的不是basic,而是一个语法和功能类似javascript的东西. 暂且称 ...
- 实现自己的脚本语言ngscript之四:代码生成
最近的进度 ngscript测试代码 function c1(a, b, c, d) { this.a = 1; this.b = new array(); this.b[0] = 1; this.b ...
- 实现自己的脚本语言ngscript之二:语法分析
ngscript的语法分析使用的是我自己的语法分析工具parseroid.与常用cc工具(yacc.bison.javacc.antlr.etc…)不同的是,parseroid生成的不是语法分析器的源 ...
- 实现自己的脚本语言ngscript之一:词法分析
正则表达式的理论基础可以参考装配脑袋的 这个 自己动手开发编译器(二)正则语言和正则表达式 这个 自己动手开发编译器(三)有穷自动机 还有这个 自己动手开发编译器(四)利用DFA转换表建立扫描器 如果 ...
- 基于 C++ 的脚本语言 cpps 脚本
cpps 脚本是一个基于 C++ 的脚本语言. 基础语法: if&else 接口说明 根据括号中数据判断执行相关代码. 代码演示 var i = toint(io.getc()); if(i ...
- 重拾《 两周自制脚本语言 》- Eclipse插件实现语法高亮
源码库: program-in-chinese/stone-editor-eclipse 参考: FAQ How do I write an editor for my own language? D ...
- L脚本语言语法手冊 0.10版
L脚本语言语法手冊 0.10版 简 介 L脚本语言是一个轻量级的,旨在接近自然语言的编程语言,眼下支持在中文.英文基础上的编程.并可扩展为随意语种.L脚本语言的语法结构简单.程序结构相对 ...
随机推荐
- CSS Text文本格式
Text Color 颜色属性被用来设置文字的颜色. 颜色是通过CSS最经常的指定: 十六进制值 - 如"#FF0000" 一个RGB值 - "RGB(255,0,0)& ...
- PowerDesigner 的几个使用技巧
1. 生成sql脚本 Database→Generate Database 选择要输出的文件路径,即文件存储路径,并根据需要修改文件名,单击确定后便会生成sql脚本. 在Options选项卡里, ...
- php 用于检测是PC还是手机访问
<?php$ua = strtolower($_SERVER['HTTP_USER_AGENT']);$uachar = "/(iphone|android|phone|mobile| ...
- Html5学习--canvas
canvas元素的实际尺寸(宽度,高度)是由标签上的属性width和height来决定的. 这两个属性不设置时默认值为:宽度=300px,高度=150px. 如果在样式表里设置width和height ...
- PHP代码分离
所谓的代码分离 其实只是一种思路,既然是一种思路 那就意味着他是有需求的 没有需求就没有解决方案 没有方案就不存在思路. 在这之前,我们制作 PHP 程序页面的时候.都是 HTML 和 PHP 混合写 ...
- 使用linux的GDB打印STL(vector,map,set..................)
在linux用gdb或者cgdb计较不爽的地方是无法打印STL的东西,所有啊去网上找了找解决方案https://www.douban.com/note/182826844/?qq-pf-to=pcqq ...
- DELPHI TMS Advanced Charts 3.8.0.3 Full Source D6-XE6 控件分享
仅供大家学习使用,请大家支持正版!! TMS Advanced Charts 3.8.0.3 Full Source D6-XE6 该控件用来画图标,压缩包里还有FOR INTRAWEB的版本 链接: ...
- WPF Canvas小例子
源码下载:DraggingElementsInCanvas_demo.rar
- nutch-1.7 编译
转载自:http://peigang.iteye.com/blog/1563288 从nutch-.3开始 本地抓取(单击) 和 分布式抓取(集群)所使用的配置文件和命令单独分开. 资源:下载地址:h ...
- Data guard RAC配置【二】
2. 利用duplicate配置容灾端 1.配置容灾端oracle用户的环境变量,这里以192.166.1.61为例. export ORACLE_BASE=/opt/oracle export OR ...