要写一个脚本引擎,首先要明确脚本长什么样,具备哪些功能,需要有怎样的能力。
Since昨天我说第一版是面向过程,强类型,无闭包,无自定义结构,支持数组,那么我将脚本设计如下:
CNScript 0.1 Draft
 
Functionality: 
Procedure Oriented, No Custom Data Structures, No Closures, Strong Typed, Array Supported.
 
Keywords:
int,double,char,string,bool,void,if,else,for,do,while,return
 
Statements:
Single Expression:
expression;
 
Chunk:
{
         Statement1
         Statement2
}
 
Array Declaration:
type name[size];
 
Variable Declaration:
type name [= expression];
 
Function definition:
type FunctionName(type paramName1, type paramName2)
Chunk
 
IF-ELSE:
if(expression)
Statement1
else
Statement2
 
FOR-LOOP:
for(statement1 expression2;expression3)
Statement
 
WHILE-LOOP:
while(expression)
Statement
 
DO-WHILE-LOOP:
do
Statement                                               
while(expression);
 
Expressions:
         Values:
                   true
                   false
                   number
                   string
                   char
                   Variable Name
                   Array Name[index]
 
         Assign:
         name = expression
 
         Function Call:
         name(expression1,expression2)
 
         Compares:
                   expression1 == expression2
                   expression1 != expression2
                   expression1 < expression2
                   expression1 > expression2
                   expression1 <= expression2
                   expression1 >= expression2
 
         Boolean Operations:
                   !expression
                   expression1 && expression2
                   expression1 || expression2
 
         Calculating:
                   expression++
                   expression—
                   ++expression
                   --expression
                   expression1 + expression2
                   expression1 – expression2
                   expression1 * expression2
                   expression1 / expression2
                   expression1 % expression2
                   expression1 ^ expression2
                   (expression)
 
Lexical Tokens:
Spaces:
         Space:                         (space_bar+)|(\n+) (\r+)|(\t+)
TypeNames:
         Type:                           (int)|(double)|(char)|(string)|(bool)|(void)
Keywords:
         Keyword_if:               if
         Keyword_else:          else
         Keyword_for:            for
         Keyword_do:             do
         Keyword_while:       while
         Keyword_return:     return
Brackets:
         BigLeftBracket:        {
         BigRightBracket:     }
         MidLeftBracket:       [
         MidRightBracket:    ]
         SmallLeftBracket:    \(
         SmallRightBracket: \)
Identifier:
         Identifier:                  (_+[a-zA-Z0-9_]+)|([a-zA-Z][a-zA-Z0-9_]*)
Number Value:
         Integer:                      0|[1-9][0-9]*
         Double:                       (0|[1-9][0-9]*)\.[0-9]+
Bool Value:
         BoolValue:                 true|false
Char:
         CharValue:                 ‘(\\[^\r\n\t])|([^’\r\n\t])’
String:
         StringValue:               “((\\”)|[^\r\n])*”                                                                                        
Operators:
         Operator:                    =|\+|-|\*|/|%|^|(++)|(--)|(&&)|(\|\|)|(!)|<|>|(<=)|(>=)|(==)|(!=)
Seprators:
         Seprator:                    ;
 
以上就是脚本设计初稿,如果后面发现有错误,会去更正的。
按这个设计,写出来的程序大概是下面这样:
 1 int Foo(int value)
 2 {
 3    return value;
 4 }
 5 
 6 void main()
 7 {
 8    int a = 100;
 9    for(int i=0;i<100;i++)
10    {
11       --a;
12    }
13    if(a>0)
14    {
15       Foo(a);
16    }
17 }
基本上就是个没模板,没类,没指针的C++了。
设计就这样了,明天开始写词法分析喔!上面的Lexical Tokens就是给词法分析用的,因为代码是字符串,我们先要把整个字符串读成一个一个的Token,才方便进行语法分析和更深入的处理,比如
int a = 100;
要先拆成[type:int] [space] [identifier:a] [space] [operator:=] [space] [integer:100] [seperator:;]
这个过程就是词法分析了。
词法分析完了得出这些Tokens然后再匹配到
Variable Declaration:
type name [= expression];
才能建立起语法树来。
Lexical Tokens中是每种Token对应的正则表达式。