Skip to content

Commit

Permalink
feat: Add for of
Browse files Browse the repository at this point in the history
  • Loading branch information
liulinboyi committed Apr 21, 2021
1 parent 296fcc4 commit 70cfa36
Show file tree
Hide file tree
Showing 75 changed files with 15,399 additions and 897 deletions.
8 changes: 8 additions & 0 deletions demo/hello-world-13.pineapple
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
func test() {
$a = "123"
for($i of $a) {
print($i)
}
}

test()
20 changes: 17 additions & 3 deletions dist/src/backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ const parser_1 = require("./parser");
const Assignment_1 = require("./parser/Assignment");
const Print_1 = require("./parser/Print");
const Comment_1 = require("./parser/Comment");
const index_js_1 = __importDefault(require("../vm/index.js"));
// import Canjs from '../vm/index.js'
const vm_1 = __importDefault(require("../vm.js/vm"));
let GlobalVariables = {
Variables: {}
};
Expand All @@ -31,8 +32,21 @@ function Execute(code) {
// console.log(JSON.stringify(ast, null, 4), '\r\rAST')
// console.log("--------------------------------------------")
// resolve
const vm = new index_js_1.default(ast);
vm.run();
// const vm = new Canjs(ast);
// vm.run()
ast.sourceType = "module";
let outast = {
program: ast,
type: "File"
};
const sanbox = { console: console };
const context = vm_1.default.createContext(sanbox);
try {
vm_1.default.runInContext(outast, "", context);
}
catch (err) {
console.error(err);
}
// resolveAST(g, ast)
}
exports.Execute = Execute;
Expand Down
3 changes: 2 additions & 1 deletion dist/src/lexer.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ TOKEN_QUOTE, // "
TOKEN_DUOQUOTE, // ""
TOKEN_NAME, // Name ::= [_A-Za-z][_0-9A-Za-z]*
TOKEN_PRINT, // print
TOKEN_IGNORED, } = Tokens;
TOKEN_IGNORED, // Ignored
} = Tokens;
exports.tokenNameMap = {
[TOKEN_EOF]: "EOF",
[TOKEN_VAR_PREFIX]: "$",
Expand Down
10 changes: 8 additions & 2 deletions dist/src/lexer1.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NewLexer = exports.Lexer = exports.tokenNameMap = exports.keywords = exports.TOKEN_IF = exports.TOKEN_FUNC_PARAMS_DIV = exports.TOKEN_RETURN = exports.BLOCK_END = exports.BLOCK_START = exports.TOKEN_FUNC = exports.Operator = exports.SourceCharacter = exports.COMMENT = exports.STRING = exports.NUMBER = exports.INTERGER = exports.TOKEN_IGNORED = exports.TOKEN_PRINT = exports.TOKEN_NAME = exports.TOKEN_DUOQUOTE = exports.TOKEN_QUOTE = exports.TOKEN_EQUAL = exports.TOKEN_RIGHT_PAREN = exports.TOKEN_LEFT_PAREN = exports.TOKEN_VAR_PREFIX = exports.TOKEN_EOF = exports.Tokens = void 0;
exports.NewLexer = exports.Lexer = exports.tokenNameMap = exports.keywords = exports.TOKEN_OF = exports.TOKEN_FOR = exports.TOKEN_IF = exports.TOKEN_FUNC_PARAMS_DIV = exports.TOKEN_RETURN = exports.BLOCK_END = exports.BLOCK_START = exports.TOKEN_FUNC = exports.Operator = exports.SourceCharacter = exports.COMMENT = exports.STRING = exports.NUMBER = exports.INTERGER = exports.TOKEN_IGNORED = exports.TOKEN_PRINT = exports.TOKEN_NAME = exports.TOKEN_DUOQUOTE = exports.TOKEN_QUOTE = exports.TOKEN_EQUAL = exports.TOKEN_RIGHT_PAREN = exports.TOKEN_LEFT_PAREN = exports.TOKEN_VAR_PREFIX = exports.TOKEN_EOF = exports.Tokens = void 0;
// token const
var Tokens;
(function (Tokens) {
Expand All @@ -26,14 +26,18 @@ var Tokens;
Tokens[Tokens["TOKEN_RETURN"] = 19] = "TOKEN_RETURN";
Tokens[Tokens["TOKEN_FUNC_PARAMS_DIV"] = 20] = "TOKEN_FUNC_PARAMS_DIV";
Tokens[Tokens["TOKEN_IF"] = 21] = "TOKEN_IF";
Tokens[Tokens["TOKEN_FOR"] = 22] = "TOKEN_FOR";
Tokens[Tokens["TOKEN_OF"] = 23] = "TOKEN_OF";
})(Tokens = exports.Tokens || (exports.Tokens = {}));
exports.TOKEN_EOF = Tokens.TOKEN_EOF, exports.TOKEN_VAR_PREFIX = Tokens.TOKEN_VAR_PREFIX, exports.TOKEN_LEFT_PAREN = Tokens.TOKEN_LEFT_PAREN, exports.TOKEN_RIGHT_PAREN = Tokens.TOKEN_RIGHT_PAREN, exports.TOKEN_EQUAL = Tokens.TOKEN_EQUAL, exports.TOKEN_QUOTE = Tokens.TOKEN_QUOTE, exports.TOKEN_DUOQUOTE = Tokens.TOKEN_DUOQUOTE, exports.TOKEN_NAME = Tokens.TOKEN_NAME, exports.TOKEN_PRINT = Tokens.TOKEN_PRINT, exports.TOKEN_IGNORED = Tokens.TOKEN_IGNORED, exports.INTERGER = Tokens.INTERGER, exports.NUMBER = Tokens.NUMBER, exports.STRING = Tokens.STRING, exports.COMMENT = Tokens.COMMENT, exports.SourceCharacter = Tokens.SourceCharacter, exports.Operator = Tokens.Operator, exports.TOKEN_FUNC = Tokens.TOKEN_FUNC, exports.BLOCK_START = Tokens.BLOCK_START, exports.BLOCK_END = Tokens.BLOCK_END, exports.TOKEN_RETURN = Tokens.TOKEN_RETURN, exports.TOKEN_FUNC_PARAMS_DIV = Tokens.TOKEN_FUNC_PARAMS_DIV, exports.TOKEN_IF = Tokens.TOKEN_IF;
exports.TOKEN_EOF = Tokens.TOKEN_EOF, exports.TOKEN_VAR_PREFIX = Tokens.TOKEN_VAR_PREFIX, exports.TOKEN_LEFT_PAREN = Tokens.TOKEN_LEFT_PAREN, exports.TOKEN_RIGHT_PAREN = Tokens.TOKEN_RIGHT_PAREN, exports.TOKEN_EQUAL = Tokens.TOKEN_EQUAL, exports.TOKEN_QUOTE = Tokens.TOKEN_QUOTE, exports.TOKEN_DUOQUOTE = Tokens.TOKEN_DUOQUOTE, exports.TOKEN_NAME = Tokens.TOKEN_NAME, exports.TOKEN_PRINT = Tokens.TOKEN_PRINT, exports.TOKEN_IGNORED = Tokens.TOKEN_IGNORED, exports.INTERGER = Tokens.INTERGER, exports.NUMBER = Tokens.NUMBER, exports.STRING = Tokens.STRING, exports.COMMENT = Tokens.COMMENT, exports.SourceCharacter = Tokens.SourceCharacter, exports.Operator = Tokens.Operator, exports.TOKEN_FUNC = Tokens.TOKEN_FUNC, exports.BLOCK_START = Tokens.BLOCK_START, exports.BLOCK_END = Tokens.BLOCK_END, exports.TOKEN_RETURN = Tokens.TOKEN_RETURN, exports.TOKEN_FUNC_PARAMS_DIV = Tokens.TOKEN_FUNC_PARAMS_DIV, exports.TOKEN_IF = Tokens.TOKEN_IF, exports.TOKEN_FOR = Tokens.TOKEN_FOR, exports.TOKEN_OF = Tokens.TOKEN_OF;
// regex match patterns
const regexName = /^[_\d\w]+/;
// 关键字
exports.keywords = {
"print": exports.TOKEN_PRINT,
"if": exports.TOKEN_IF,
"for": exports.TOKEN_FOR,
"of": exports.TOKEN_OF
};
exports.tokenNameMap = {
[exports.TOKEN_EOF]: "EOF",
Expand All @@ -58,6 +62,8 @@ exports.tokenNameMap = {
[exports.TOKEN_RETURN]: "TOKEN_RETURN",
[exports.TOKEN_FUNC_PARAMS_DIV]: "TOKEN_FUNC_PARAMS_DIV",
[exports.TOKEN_IF]: "if",
[exports.TOKEN_FOR]: "for",
[exports.TOKEN_OF]: "of",
};
class Lexer {
constructor(sourceCode, lineNum, nextToken, nextTokenType, nextTokenLineNum) {
Expand Down
1 change: 1 addition & 0 deletions dist/src/parser/Expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ function parseExpression(lexer) {
type: "CallExpression",
callee: {
type: "Identifier",
// name: ""
},
arguments: []
}
Expand Down
70 changes: 70 additions & 0 deletions dist/src/parser/ForOfStatement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseForStatement = void 0;
const lexer1_1 = require("../lexer1");
const parser_1 = require("../parser");
const Assignment_1 = require("./Assignment");
const Function_1 = require("./Function");
function parseForStatement(lexer) {
lexer.NextTokenIs(lexer1_1.TOKEN_FOR);
lexer.LookAheadAndSkip(lexer1_1.TOKEN_IGNORED);
lexer.NextTokenIs(lexer1_1.TOKEN_LEFT_PAREN); // (
const ForOfStatement = parseBinaryExpression(lexer);
lexer.NextTokenIs(lexer1_1.TOKEN_RIGHT_PAREN); // )
lexer.LookAheadAndSkip(lexer1_1.TOKEN_IGNORED);
lexer.NextTokenIs(lexer1_1.BLOCK_START); // {
lexer.LookAheadAndSkip(lexer1_1.TOKEN_IGNORED); // 去除空格回车等
const BlockStatementBody = [];
const consequent = {
type: "BlockStatement",
body: []
};
consequent.body = Function_1.paseBlock(lexer, BlockStatementBody);
lexer.NextTokenIs(lexer1_1.BLOCK_END);
lexer.LookAheadAndSkip(lexer1_1.TOKEN_IGNORED); // 去除空格回车等
ForOfStatement.body = consequent;
return ForOfStatement;
}
exports.parseForStatement = parseForStatement;
function parseBinaryExpression(lexer) {
const ForOfStatement = {
type: "ForOfStatement",
await: false,
left: {
type: "VariableDeclaration",
declarations: [
{
type: "VariableDeclarator",
id: {
type: "Identifier",
name: ""
},
init: null
}
],
kind: "let"
},
// operator: "",
right: {
type: "Identifier",
// name: "b"
}
};
const Variable = parser_1.parseVariable(lexer); // 标识符,这里面会把邻近的空格回车删掉
const identifier = new Assignment_1.Identifier(Variable.Name);
lexer.NextTokenIs(lexer1_1.TOKEN_OF);
// BinaryExpression.operator = (lexer.NextTokenIs(Operator)).nowToken; // +-*/
lexer.LookAheadAndSkip(lexer1_1.TOKEN_IGNORED); // 空格
let ahead = lexer.LookAhead();
ForOfStatement.left.declarations[0].id = new Assignment_1.Identifier(identifier.name);
if (ahead.tokenType === lexer1_1.NUMBER) {
const literial = new Assignment_1.Literal(parser_1.parseNumber(lexer));
ForOfStatement.right = literial;
}
else if (ahead.tokenType === lexer1_1.TOKEN_VAR_PREFIX) {
const Variable = parser_1.parseVariable(lexer); // 标识符
const identifier = new Assignment_1.Identifier(Variable.Name);
ForOfStatement.right = identifier;
}
return ForOfStatement;
}
7 changes: 7 additions & 0 deletions dist/src/parser/Function.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ const lexer1_1 = require("../lexer1");
const parser_1 = require("../parser");
const Assignment_1 = require("./Assignment");
const IfStatement_1 = require("./IfStatement");
const ForOfStatement_1 = require("./ForOfStatement");
const Print_1 = require("./Print");
function parseFunction(lexer) {
const FunctionDeclaration = {
type: "FunctionDeclaration",
id: {
type: "Identifier",
// name: ""
},
params: [
// {
Expand Down Expand Up @@ -99,6 +101,11 @@ function paseBlock(lexer, BlockStatementBody) {
BlockStatementBody.push(IfStatement);
paseBlock(lexer, BlockStatementBody);
}
else if (ahead.tokenType === lexer1_1.TOKEN_FOR) {
const ForStatement = ForOfStatement_1.parseForStatement(lexer);
BlockStatementBody.push(ForStatement);
paseBlock(lexer, BlockStatementBody);
}
// else if (ahead.tokenType === TOKEN_NAME) {
// const ExpressionStatement = parseExpression(lexer)
// }
Expand Down
2 changes: 1 addition & 1 deletion dist/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
const fs = require('fs');
const path = require('path');
const Execute = require('../dist/src/backend.js').Execute;
code = fs.readFileSync(path.resolve(__dirname, '../demo/hello-world-11.pineapple'), { encoding: 'utf-8' });
code = fs.readFileSync(path.resolve(__dirname, '../demo/hello-world-13.pineapple'), { encoding: 'utf-8' });
console.log(code, 'code');
if (code.length > 0) {
Execute(code);
Expand Down
9 changes: 9 additions & 0 deletions dist/vm.js/Prototype.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Prototype = void 0;
class Prototype {
constructor(constructor) {
this.constructor = constructor;
}
}
exports.Prototype = Prototype;
9 changes: 9 additions & 0 deletions dist/vm.js/This.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.This = void 0;
class This {
constructor(context) {
this.context = context;
}
}
exports.This = This;
11 changes: 11 additions & 0 deletions dist/vm.js/constant.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ANONYMOUS = exports.NEW = exports.ARGUMENTS = exports.UNDEFINED = exports.REQUIRE = exports.EXPORTS = exports.MODULE = exports.THIS = void 0;
exports.THIS = "this";
exports.MODULE = "module";
exports.EXPORTS = "exports";
exports.REQUIRE = "require";
exports.UNDEFINED = "undefined";
exports.ARGUMENTS = "arguments";
exports.NEW = "new";
exports.ANONYMOUS = "anonymous";
149 changes: 149 additions & 0 deletions dist/vm.js/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Context = exports.DEFAULT_CONTEXT = void 0;
const constant_1 = require("./constant");
// ECMA standar refs: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects
exports.DEFAULT_CONTEXT = {
Function,
Array,
Boolean,
clearInterval,
clearTimeout,
console,
Date,
decodeURI,
decodeURIComponent,
encodeURI,
encodeURIComponent,
Error,
escape,
eval,
EvalError,
Infinity,
isFinite,
isNaN,
JSON,
Math,
NaN,
Number,
["null"]: null,
[constant_1.UNDEFINED]: void 0,
Object,
parseFloat,
parseInt,
RangeError,
ReferenceError,
RegExp,
setInterval,
setTimeout,
String,
SyntaxError,
TypeError,
unescape,
URIError
};
// need to polyfill by user
/* istanbul ignore if */
if (typeof Promise !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Promise = Promise;
}
/* istanbul ignore if */
if (typeof Proxy !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Proxy = Proxy;
}
/* istanbul ignore if */
if (typeof Reflect !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Reflect = Reflect;
}
/* istanbul ignore if */
if (typeof Symbol !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Symbol = Symbol;
}
/* istanbul ignore if */
if (typeof Set !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Set = Set;
}
/* istanbul ignore if */
if (typeof WeakSet !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.WeakSet = WeakSet;
}
/* istanbul ignore if */
if (typeof Map !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Map = Map;
}
/* istanbul ignore if */
if (typeof WeakMap !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.WeakMap = WeakMap;
}
/* istanbul ignore if */
if (typeof ArrayBuffer !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.ArrayBuffer = ArrayBuffer;
}
/* istanbul ignore if */
if (typeof SharedArrayBuffer !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.ArrayBuffer = SharedArrayBuffer;
}
/* istanbul ignore if */
if (typeof DataView !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.ArrayBuffer = DataView;
}
/* istanbul ignore if */
if (typeof Atomics !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Atomics = Atomics;
}
/* istanbul ignore if */
if (typeof Float32Array !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Float32Array = Float32Array;
}
/* istanbul ignore if */
if (typeof Float64Array !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Float64Array = Float64Array;
}
/* istanbul ignore if */
if (typeof Int16Array !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Int16Array = Int16Array;
}
/* istanbul ignore if */
if (typeof Int32Array !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Int32Array = Int32Array;
}
/* istanbul ignore if */
if (typeof Int8Array !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Int32Array = Int8Array;
}
/* istanbul ignore if */
if (typeof Intl !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Intl = Intl;
}
/* istanbul ignore if */
if (typeof Uint16Array !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Uint16Array = Uint16Array;
}
/* istanbul ignore if */
if (typeof Uint32Array !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Uint32Array = Uint32Array;
}
/* istanbul ignore if */
if (typeof Uint8Array !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Uint8Array = Uint8Array;
}
/* istanbul ignore if */
if (typeof Uint8ClampedArray !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.Uint8ClampedArray = Uint8ClampedArray;
}
/* istanbul ignore if */
if (typeof WebAssembly !== constant_1.UNDEFINED) {
exports.DEFAULT_CONTEXT.WebAssembly = WebAssembly;
}
class Context {
constructor(externalContext = {}) {
const ctx = { ...exports.DEFAULT_CONTEXT, ...externalContext };
for (const attr in ctx) {
/* istanbul ignore next */
if (ctx.hasOwnProperty(attr)) {
this[attr] = ctx[attr];
}
}
}
}
exports.Context = Context;
Loading

0 comments on commit 70cfa36

Please sign in to comment.