这是第四篇了,之所以隔了这么久才写,一方面是因为最近开始实习了,另一方面是因为设计语法真是要考虑很多东西。

于是我去读了这本书,里面实现了两种语言,一种跟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之三:语法设计的更多相关文章

  1. 关于JS脚本语言的基础语法

    JS脚本语言的基础语法:输出语法  alert("警告!");  confirm("确定吗?");   prompt("请输入密码");为弱 ...

  2. Cocos2d-x 脚本语言Lua基本语法

    Cocos2d-x 脚本语言Lua基本语法 前面一篇博客对Lua这门小巧的语言进行了简单的介绍.本篇博客来给大家略微讲一下Lua的语法.不会长篇累牍得把Lua的全部语法都讲一遍,这里通过下面几点来讲L ...

  3. 实现自己的脚本语言ngscript之零

    正式开始介绍前先扯点没用的. 从小玩basic长大的小朋友大多有一个梦想,就是自己实现一个basic解释器. 不过这里我实现的不是basic,而是一个语法和功能类似javascript的东西. 暂且称 ...

  4. 实现自己的脚本语言ngscript之四:代码生成

    最近的进度 ngscript测试代码 function c1(a, b, c, d) { this.a = 1; this.b = new array(); this.b[0] = 1; this.b ...

  5. 实现自己的脚本语言ngscript之二:语法分析

    ngscript的语法分析使用的是我自己的语法分析工具parseroid.与常用cc工具(yacc.bison.javacc.antlr.etc…)不同的是,parseroid生成的不是语法分析器的源 ...

  6. 实现自己的脚本语言ngscript之一:词法分析

    正则表达式的理论基础可以参考装配脑袋的 这个 自己动手开发编译器(二)正则语言和正则表达式 这个 自己动手开发编译器(三)有穷自动机 还有这个 自己动手开发编译器(四)利用DFA转换表建立扫描器 如果 ...

  7. 基于 C++ 的脚本语言 cpps 脚本

    cpps 脚本是一个基于 C++ 的脚本语言. 基础语法: if&else 接口说明 根据括号中数据判断执行相关代码. 代码演示 var i = toint(io.getc()); if(i  ...

  8. 重拾《 两周自制脚本语言 》- Eclipse插件实现语法高亮

    源码库: program-in-chinese/stone-editor-eclipse 参考: FAQ How do I write an editor for my own language? D ...

  9. L脚本语言语法手冊 0.10版

    L脚本语言语法手冊 0.10版       简  介 L脚本语言是一个轻量级的,旨在接近自然语言的编程语言,眼下支持在中文.英文基础上的编程.并可扩展为随意语种.L脚本语言的语法结构简单.程序结构相对 ...

随机推荐

  1. iOS中的几种定时器详解

    在软件开发过程中,我们常常需要在某个时间后执行某个方法,或者是按照某个周期一直执行某个方法.在这个时候,我们就需要用到定时器. 然而,在iOS中有很多方法完成以上的任务,经过查阅资料,大概有三种方法: ...

  2. 完全背包的变形POJ1252

    话说今天做背包做到有点累了,题目是英文的--而且还很长,我看了好久(弱爆了). 题目大概的意思就是,有六种硬币,之后,求用这六种硬币最小数目支付1到100美分的平均值,以及最小数目中的最大值. 很容易 ...

  3. ACM HDU 1021 Fibonacci Again

    #include<iostream> using namespace std; int main() { int n; while(cin>>n) { if((n+1)%4== ...

  4. 理解ThreadLocal背后的概念

    介绍 我之前在任何场合都没有使用过thread local,因此没有注意到它,直到最近用到它的时候. 前提信息 线程可以理解为一个单独的进程,它有自己的调用栈.在java中每一个线程都有一个调用栈或者 ...

  5. jQuery EasyUI 1.4.4 Combobox无法检索中文输入的问题

    在项目里使用了EasyUI的Combobox,当ComboBox的item是英文时,都能正常检索出对应项,但是如果使用中文输入法输入几个字母然后通过按shift键输入时,奇怪的事情发生了,combob ...

  6. 桂电在线-php-提取菜单到配置文件2

    继续昨晚没完成的主菜单模板: <!-- 菜单块 --> <div class="on-light" id="menus"> <?p ...

  7. mysql的数据类型int、bigint、smallint 和 tinyint取值范围 及varchar

    使用整数数据的精确数字数据类型.   bigint   从 -2^63 (-9223372036854775808) 到 2^63-1 (9223372036854775807) 的整型数据(所有数字 ...

  8. WPF Window对象

    户通过窗口与 Windows Presentation Foundation (WPF) 独立应用程序进行交互.窗口的主要用途是承载可视化数据并使用户可以与数据进行交互的内容.独立 WPF 应用程序使 ...

  9. Bag of Words/Bag of Features的Matlab源码发布

    2010年11月19日 ⁄ 技术, 科研 ⁄ 共 1296字 ⁄ 评论数 26 ⁄ 被围观 4,150 阅读+ 由于自己以前发过一篇文章讲bow特征的matlab代码的优化的<Bag-Of-Wo ...

  10. C# this.Invoke()的作用和用法(摘)

    Invoke()的作用是:在应用程序的主线程上执行指定的委托.一般应用:在辅助线程中修改UI线程( 主线程 )中对象的属性时,调用this.Invoke();   在多线程编程中,我们经常要在工作线程 ...