用 c++实现的 js 解释器的子集。以字节码解释运行。 字节码指令解释部分,参考自mocha1995
//进入REPL
make cmd&&./cmd.out
make test
//test.cpp
machine->process("\
function getAdd() {\
function add(a,b) {\
return a+b;\
}\
return add;\
}\
var outAdd = getAdd();\
var c=outAdd(1,2);\
");
- 词法分析
- 参考mocha1995的词法解析
- 算法逻辑采用了 NFA 有限自动机
LB: [
RB: ] //数组标识
LC: {
RC: }
LP: (
RP: ) //函数声明和调用标识
COMMA: ',' //数组或者多个声明标识 ,
ASSIGN: =,+=,-= //赋值符号 =,+=,-=
HOOK: ? //条件判断符号 ?
COLON: : //三目符号中的:
OR: ||
AND: &&
BITOR: |
BITXOR: ^
BITAND: &
EQOP: ==,!= //等于符号
RELOP: < <= > >= //比较符号
SHOP: << >> >>> //移位符号
PLUS: +
MINUS: -
MULOP: * / %
UNARYOP: ! ~ //一元前缀符号 !=的! 和~
INCOP: ++ -- //自增和自减符号
DOT: . //成员访问符号 .
NAME: [a-zA-Z]([a-zA-Z_][0-9])* //标识符
NUMBER: [0-9].?[0-9] //数字常量
STRING: [a-zA-Z]([a-zA-Z_][0-9])* //字符串常量
PRIMARY: true,false,null,this,super
//关键字
FUNCTION: function //函数关键字 函数定义用
IF: if //if关键字 bool判断true用
ELSE: else //else关键字 bool判断false用
SWITCH: switch //switch关键字 匹配值用
CASE: case //case关键字 每种case对应处理用
DEFAULT: default //default关键字 没有匹配时用
WHILE: while //while关键字 while循环判断用
DO: do //do关键字 do-while循环入口
FOR: for //for关键字 for循环入口
BREAK: break //break关键字 循环调出
CONTINUE: continue //continue关键字 跳过这次,继续循环下一个
IN: in //in关键字 for循环取出对象属性用
VAR: var //var关键字 变量声明
WITH: with //with关键字 with作用域
RETURN: return //return关键字 函数返回用
NEW: new //new关键字 创建对象
RESERVED: reserved //保留关键字
- 语法分析
- 依据EBNF(扩展巴克斯范式)的语法规则来实现生成 AST
stmt : varDecl | assignmentStat | expStmt | returnStmt | functionDecl | callExp ; //语句
functionDecl : Function Identifier '(' Identifier (',' Identifier)* ')' ; //函数定义
block : '{' (stmt)* '}' ; //块语句
varDecl : Var Identifier ('=' exp)? ';' ; //var变量初始化
assignmentStat : Identifier '=' exp ; //变量赋值
returnStmt : Return stmt ; //返回语句
expStmt : exp ';' //表达式语句
unaryExp : [!, ~] pri ; //一元表达式
callExp : Identifier '(' pri (',',pri)* ')' ; //调用表达式
binaryExp : [<<,>>,==,!=,<,<=,>,>=,+,-,*,/] ; //二元表达式
exp : add ; //表达式
add : mul ('+' mul)* ;//加法表达式
mul : pri ('*' pri)* ;//乘法表达式
pri : NumberLiteral | Identifier | '(' exp ')' ; //基础表达式
- 运行时(解释执行字节码指令)
- 算数表达式
- 变量赋值
- 函数调用
- 函数一等公民
- 嵌套函数
- DFA 确定的有限自动机
状态机在任何一个状态,基于输入的字符,都能做一个确定的状态转换。不会产生回溯
- NFA 不确定的有限自动机
存在某些状态,针对某些输入,不能做一个确定的转换。会回溯