使用bison和yacc制作脚本语言2

我们先来想一下语法

一般脚本语言不需要定义类型直接在赋值的时候确定

  1. 我们主要考虑一下变量的类型
a = 1;
b = 1.1;
c = "str";

一般来讲,我们使用这三种类型,整形,浮点型,字符串型

不过我们以后还可能使用原生类型等

  1. 变量的基本运算和其他语言基本相同
a = b + 12.4;
c = "hehe" + a + "haha"
  1. 函数定义 我们可以模仿一下js的函数定义方式,不过变量使用的时候我们需要声明才可以使用全局变量
function func(){global outervar;}
  1. 简单的流程控制
for(a = 0;a<10;a++) {break;continue;}
if(a){}

文法

我们先简单写一下文法,因为bison是LALR文法,注意一下和LL系列文法的区别

如果是自己要制作编程语言的话不妨参考一下C语言的bison文法:http://www.quut.com/c/ANSI-C-grammar-y-1998.html

一般情况下,非终结符我们规定都是小写的,终结符都是大写的

先看开头部分

translation_unit: definition_or_statement 
        | translation_unit definition_or_statement 
        ;

我们认为所有的语句,函数等都会规约成 translation_unit ,多个语句或者是定义可以被规约成一个,

|是代表或的意思,;这小段文法的结束

definition_or_statement:function_definition
        |statement
        ;

一般语句和定义可以由语句或者函数定义规约

函数定义我们认为类似于这样的 function funcname(arg1,arg2){} 和下面对应,我们可以定义有参数和无参的函数

function_definition: FUNCTION IDENTIFIER LP arglist RP block
        |FUNCTION IDENTIFIER LP RP block
        ;

语句:

statement:expression_statement
        |global_declaration
        |for_statement 
        |if_statement
        |break_statement
        |continue_statement
        |return_statement
        ;

表达式语句:我们每个语句都是由;结尾的,SEMICOLON就是分号

expression_statement:expression SEMICOLON
        ;

表达式 一般就都有值,可以计算的,比如赋值,加减乘除计算等等

LALR 文法一般是运算级高的先规约,一般情况下常量先规约,一般是单目运算符,括号,函数调用先规约

primary_expression:SUB primary_expression /* 取负 */
        |LP expression RP /* 括号 */
        |IDENTIFIER /* 变量名 */
        |STRING_LITERAL /* 字符串 */
        |INT_LITERAL /* 整数 */
        |DOUBLE_LITERAL /* 浮点 */
        |IDENTIFIER LP RP /* 无参数函数调用 */
        |IDENTIFIER LP arglist RP
        ;

下面开始简单的四则运算乘除法会比加减有更高的优先级别,所以primary_expression优先规约成mul_div_expression

mul_div_expression:primary_expression
        |mul_div_expression DIV primary_expression
        |mul_div_expression MUL primary_expression
        ;

加减法:

add_sub_expression:mul_div_expression 
        |add_sub_expression ADD mul_div_expression
        |add_sub_expression SUB mul_div_expression
        ;

同理比较运算和等于不等于运算省略

上面的可以规约为赋值表达式 (ASSIGN 是等于=在lex文件中定义)

expression: value_expression
        |IDENTIFIER ASSIGN expression

表达式可以在上面规约为语句,因此表达式部分的文法就完成了

if语句也很简单

if_statement: IF LP expression RP block
        ;

for语句:

for_statement: FOR LP expression_option SEMICOLON expression_option SEMICOLON expression_option  RP block
    ;

程序块:

block:LC RC
    |LC statement_list RC
    ;

break,return,continue都一样

break_statement:BREAK SEMICOLON
        ;
continue_statement:CONTINUE SEMICOLON
        ;

还有一些没解释的都很容易理解

现在已经定义的全部文法:

translation_unit: definition_or_statement 
        | translation_unit definition_or_statement
        ;
definition_or_statement:function_definition
        |statement
        ;
function_definition: FUNCTION IDENTIFIER LP arglist RP block
        |
        FUNCTION IDENTIFIER LP RP block
        ;
statement:expression_statement
        |global_declaration
        |for_statement 
        |if_statement
        |break_statement
        |continue_statement
        |return_statement
        ;
expression_statement:expression SEMICOLON
        ;
expression: value_expression
        |IDENTIFIER ASSIGN expression
        ;
value_expression: compare_expression
        |value_expression EQ compare_expression
        |value_expression NE compare_expression
        ;
compare_expression:add_sub_expression 
        |compare_expression GT add_sub_expression
        |compare_expression GE add_sub_expression
        |compare_expression LT add_sub_expression
        |compare_expression LE add_sub_expression
        ;
add_sub_expression:mul_div_expression 
        |add_sub_expression ADD mul_div_expression
        |add_sub_expression SUB mul_div_expression
        ;
mul_div_expression:primary_expression
        |mul_div_expression DIV primary_expression
        |mul_div_expression MUL primary_expression
        ;
primary_expression:SUB primary_expression
        |LP expression RP
        |IDENTIFIER
        |STRING_LITERAL
        |INT_LITERAL
        |DOUBLE_LITERAL
        |IDENTIFIER LP RP
        |IDENTIFIER LP arglist RP
        ;
statement_list:statement_list statement
        |statement
        ;
block:LC RC
        |LC statement_list RC

        ;
arglist:arglist COMMA arg
        |
        arg
        ;
arg:    IDENTIFIER
        ;
expression_option:
        |expression
        ;
for_statement: FOR LP expression_option SEMICOLON expression_option SEMICOLON expression_option  RP block
        ;
if_statement: IF LP expression RP block
        ;
break_statement:BREAK SEMICOLON
        ;
continue_statement:CONTINUE SEMICOLON
        ;
return_statement:RETURN IDENTIFIER
        ;
global_declaration:GLOBAL IDENTIFIER
        ;
上一篇:asp.net不能调试,配置一切正常


下一篇:[转帖]迅为4412开发板最小linux系统的存储空间修改