Skip to content

Commit

Permalink
fix: BinaryExpression error
Browse files Browse the repository at this point in the history
  • Loading branch information
liulinboyi committed Feb 26, 2021
1 parent 5dbc409 commit be169ae
Show file tree
Hide file tree
Showing 15 changed files with 318 additions and 148 deletions.
8 changes: 3 additions & 5 deletions demo/hello-world-2.pineapple
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
#$a = 0
$b = 1
#print($b)
#$e = "啊哈哈哈哈"
$c = $b
print($c)
$d = $b - 1
print($b)
print($d)
4 changes: 4 additions & 0 deletions demo/hello-world-3.pineapple
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
$b = 1
$d = $b - $b
print($b)
print($d)
12 changes: 12 additions & 0 deletions demo/hello-world-4.pineapple
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
$a = 10
$b = $a- 5
$d = 3 -2
$c = 25 - $a
$e = 100 * 100
$f = 1/2
print($a)
print($b)
print($d)
print($c)
print($e)
print($f)
82 changes: 39 additions & 43 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.Tokens = void 0;
exports.NewLexer = exports.Lexer = exports.tokenNameMap = exports.keywords = 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 @@ -19,44 +19,32 @@ var Tokens;
Tokens[Tokens["STRING"] = 12] = "STRING";
Tokens[Tokens["COMMENT"] = 13] = "COMMENT";
Tokens[Tokens["SourceCharacter"] = 14] = "SourceCharacter";
Tokens[Tokens["Operator"] = 15] = "Operator";
})(Tokens = exports.Tokens || (exports.Tokens = {}));
const { TOKEN_EOF, // end-of-file
TOKEN_VAR_PREFIX, // $
TOKEN_LEFT_PAREN, // (
TOKEN_RIGHT_PAREN, // )
TOKEN_EQUAL, // =
TOKEN_QUOTE, // "
TOKEN_DUOQUOTE, // ""
TOKEN_NAME, // Name ::= [_A-Za-z][_0-9A-Za-z]*
TOKEN_PRINT, // print
TOKEN_IGNORED, // Ignored
INTERGER, // [0-9]+
NUMBER, // Integer Ignored
STRING, // String ::= '"' '"' Ignored | '"' StringCharacter '"' Ignored
COMMENT, // Ignored "#" SourceCharacter Ignored
SourceCharacter, } = 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;
// regex match patterns
const regexName = /^[_\d\w]+/;
// 关键字
exports.keywords = {
"print": TOKEN_PRINT,
"print": exports.TOKEN_PRINT,
};
exports.tokenNameMap = {
[TOKEN_EOF]: "EOF",
[TOKEN_VAR_PREFIX]: "$",
[TOKEN_LEFT_PAREN]: "(",
[TOKEN_RIGHT_PAREN]: ")",
[TOKEN_EQUAL]: "=",
[TOKEN_QUOTE]: "\"",
[TOKEN_DUOQUOTE]: "\"\"",
[TOKEN_NAME]: "Name",
[TOKEN_PRINT]: "print",
[TOKEN_IGNORED]: "Ignored",
[INTERGER]: "INTERGER",
[NUMBER]: "NUMBER",
[STRING]: "STRING",
[COMMENT]: "COMMENT",
[SourceCharacter]: "SourceCharacter",
[exports.TOKEN_EOF]: "EOF",
[exports.TOKEN_VAR_PREFIX]: "$",
[exports.TOKEN_LEFT_PAREN]: "(",
[exports.TOKEN_RIGHT_PAREN]: ")",
[exports.TOKEN_EQUAL]: "=",
[exports.TOKEN_QUOTE]: "\"",
[exports.TOKEN_DUOQUOTE]: "\"\"",
[exports.TOKEN_NAME]: "Name",
[exports.TOKEN_PRINT]: "print",
[exports.TOKEN_IGNORED]: "Ignored",
[exports.INTERGER]: "INTERGER",
[exports.NUMBER]: "NUMBER",
[exports.STRING]: "STRING",
[exports.COMMENT]: "COMMENT",
[exports.SourceCharacter]: "SourceCharacter",
[exports.Operator]: "Operator",
};
class Lexer {
constructor(sourceCode, lineNum, nextToken, nextTokenType, nextTokenLineNum) {
Expand Down Expand Up @@ -146,11 +134,11 @@ class Lexer {
// console.log(this.sourceCode[0], '当前Token')
// check ignored
if (this.isIgnored()) {
return { lineNum: this.lineNum, tokenType: TOKEN_IGNORED, token: "Ignored" };
return { lineNum: this.lineNum, tokenType: exports.TOKEN_IGNORED, token: "Ignored" };
}
// finish
if (this.sourceCode.length == 0) {
return { lineNum: this.lineNum, tokenType: TOKEN_EOF, token: exports.tokenNameMap[TOKEN_EOF] };
return { lineNum: this.lineNum, tokenType: exports.TOKEN_EOF, token: exports.tokenNameMap[exports.TOKEN_EOF] };
}
// 如果nextTokenType是#,并且字符串能匹配上,则表示是源代码字符串
// if (this.sourceCode[0].match(/\*/)) {
Expand All @@ -160,26 +148,32 @@ class Lexer {
switch (this.sourceCode[0]) {
case '$':
this.skipSourceCode(1);
return { lineNum: this.lineNum, tokenType: TOKEN_VAR_PREFIX, token: "$" };
return { lineNum: this.lineNum, tokenType: exports.TOKEN_VAR_PREFIX, token: "$" };
case '(':
this.skipSourceCode(1);
return { lineNum: this.lineNum, tokenType: TOKEN_LEFT_PAREN, token: "(" };
return { lineNum: this.lineNum, tokenType: exports.TOKEN_LEFT_PAREN, token: "(" };
case ')':
this.skipSourceCode(1);
return { lineNum: this.lineNum, tokenType: TOKEN_RIGHT_PAREN, token: ")" };
return { lineNum: this.lineNum, tokenType: exports.TOKEN_RIGHT_PAREN, token: ")" };
case '=':
this.skipSourceCode(1);
return { lineNum: this.lineNum, tokenType: TOKEN_EQUAL, token: "=" };
return { lineNum: this.lineNum, tokenType: exports.TOKEN_EQUAL, token: "=" };
case '"':
if (this.nextSourceCodeIs("\"\"")) {
this.skipSourceCode(2);
return { lineNum: this.lineNum, tokenType: TOKEN_DUOQUOTE, token: "\"\"" };
return { lineNum: this.lineNum, tokenType: exports.TOKEN_DUOQUOTE, token: "\"\"" };
}
this.skipSourceCode(1);
return { lineNum: this.lineNum, tokenType: TOKEN_QUOTE, token: "\"" };
return { lineNum: this.lineNum, tokenType: exports.TOKEN_QUOTE, token: "\"" };
case '#':
this.skipSourceCode(1);
return { lineNum: this.lineNum, tokenType: COMMENT, token: "#" };
return { lineNum: this.lineNum, tokenType: exports.COMMENT, token: "#" };
}
// Operator
if (/\+|\-|\*|\//.test(this.sourceCode[0])) {
const op = this.sourceCode[0];
this.skipSourceCode(1);
return { lineNum: this.lineNum, tokenType: exports.Operator, token: op };
}
// check multiple character token
if (this.sourceCode[0] == '_' || this.isLetter(this.sourceCode[0])) {
Expand All @@ -191,11 +185,13 @@ class Lexer {
return { lineNum: this.lineNum, tokenType, token };
}
else {
return { lineNum: this.lineNum, tokenType: TOKEN_NAME, token };
return { lineNum: this.lineNum, tokenType: exports.TOKEN_NAME, token };
}
}
if (this.isNumber(this.sourceCode[0])) {
return { lineNum: this.lineNum, tokenType: NUMBER, token: this.sourceCode[0] };
const num = this.sourceCode[0];
this.skipSourceCode(1);
return { lineNum: this.lineNum, tokenType: exports.NUMBER, token: num };
}
// unexpected symbol
throw new Error(`MatchToken(): unexpected symbol near '${this.sourceCode[0]}'.`);
Expand Down
53 changes: 26 additions & 27 deletions dist/src/parser.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parse = exports.parseString = exports.parseNumber = exports.parseVariable = exports.Program = 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 = void 0;
exports.parse = exports.parseString = exports.parseNumber = exports.parseVariable = exports.Program = void 0;
const lexer1_1 = require("./lexer1");
const Comment_1 = require("./parser/Comment");
const Print_1 = require("./parser/Print");
const Assignment_1 = require("./parser/Assignment");
exports.TOKEN_EOF = lexer1_1.Tokens.TOKEN_EOF, exports.TOKEN_VAR_PREFIX = lexer1_1.Tokens.TOKEN_VAR_PREFIX, exports.TOKEN_LEFT_PAREN = lexer1_1.Tokens.TOKEN_LEFT_PAREN, exports.TOKEN_RIGHT_PAREN = lexer1_1.Tokens.TOKEN_RIGHT_PAREN, exports.TOKEN_EQUAL = lexer1_1.Tokens.TOKEN_EQUAL, exports.TOKEN_QUOTE = lexer1_1.Tokens.TOKEN_QUOTE, exports.TOKEN_DUOQUOTE = lexer1_1.Tokens.TOKEN_DUOQUOTE, exports.TOKEN_NAME = lexer1_1.Tokens.TOKEN_NAME, exports.TOKEN_PRINT = lexer1_1.Tokens.TOKEN_PRINT, exports.TOKEN_IGNORED = lexer1_1.Tokens.TOKEN_IGNORED, exports.INTERGER = lexer1_1.Tokens.INTERGER, exports.NUMBER = lexer1_1.Tokens.NUMBER, exports.STRING = lexer1_1.Tokens.STRING, exports.COMMENT = lexer1_1.Tokens.COMMENT, exports.SourceCharacter = lexer1_1.Tokens.SourceCharacter;
class Program {
constructor(type, body, LineNum) {
this.type = 'Program';
Expand Down Expand Up @@ -37,55 +36,55 @@ function parseStatements(lexer) {
}
function parseStatement(lexer) {
// 向前看一个token并跳过
lexer.LookAheadAndSkip(exports.TOKEN_IGNORED); // skip if source code start with ignored token
lexer.LookAheadAndSkip(lexer1_1.TOKEN_IGNORED); // skip if source code start with ignored token
let look = lexer.LookAhead().tokenType;
console.log(look, 'look');
switch (look) {
case exports.TOKEN_PRINT:
case lexer1_1.TOKEN_PRINT:
return Print_1.parsePrint(lexer);
case exports.TOKEN_VAR_PREFIX:
case lexer1_1.TOKEN_VAR_PREFIX:
return Assignment_1.parseAssignment(lexer);
case exports.COMMENT:
case lexer1_1.COMMENT:
return Comment_1.paseComment(lexer);
default:
throw new Error("parseStatement(): unknown Statement.");
}
}
function isSourceCodeEnd(token) {
return token === exports.TOKEN_EOF;
return token === lexer1_1.TOKEN_EOF;
}
// Variable ::= "$" Name Ignored
function parseVariable(lexer) {
let variable = { Name: '' };
variable.LineNum = lexer.GetLineNum();
lexer.NextTokenIs(exports.TOKEN_VAR_PREFIX);
lexer.NextTokenIs(lexer1_1.TOKEN_VAR_PREFIX);
variable.Name = parseName(lexer);
lexer.LookAheadAndSkip(exports.TOKEN_IGNORED);
lexer.LookAheadAndSkip(lexer1_1.TOKEN_IGNORED);
return variable;
}
exports.parseVariable = parseVariable;
// Name ::= [_A-Za-z][_0-9A-Za-z]*
function parseName(lexer) {
let { nowLineNum: _, nowToken: name } = lexer.NextTokenIs(exports.TOKEN_NAME);
let { nowLineNum: _, nowToken: name } = lexer.NextTokenIs(lexer1_1.TOKEN_NAME);
return name;
}
// Integer ::= [0-9]+
// Number ::= Integer Ignored
function parseNumber(lexer) {
let str = "";
let { tokenType, token } = lexer.MatchToken();
let { tokenType, token } = lexer.LookAhead();
str += token;
// console.log(tokenType, 'parseNumber', str, 'str')
if (tokenType === exports.NUMBER) {
if (tokenType === lexer1_1.NUMBER) {
while (lexer.isNumber(lexer.sourceCode[0])) {
// console.log(lexer.sourceCode[0])
str = lexer.next(1);
str += lexer.next(1);
}
if (!lexer.isIgnored()) {
throw new Error('Uncaught SyntaxError: Invalid or unexpected token');
}
lexer.NextTokenIs(exports.NUMBER);
lexer.LookAheadAndSkip(exports.TOKEN_IGNORED);
// if (!lexer.isIgnored()) {
// throw new Error('Uncaught SyntaxError: Invalid or unexpected token')
// }
lexer.NextTokenIs(lexer1_1.NUMBER);
lexer.LookAheadAndSkip(lexer1_1.TOKEN_IGNORED);
}
return +str;
}
Expand All @@ -95,15 +94,15 @@ function parseString(lexer) {
let str = "";
let look = lexer.LookAhead().tokenType;
switch (look) {
case exports.TOKEN_DUOQUOTE:
lexer.NextTokenIs(exports.TOKEN_DUOQUOTE);
lexer.LookAheadAndSkip(exports.TOKEN_IGNORED);
case lexer1_1.TOKEN_DUOQUOTE:
lexer.NextTokenIs(lexer1_1.TOKEN_DUOQUOTE);
lexer.LookAheadAndSkip(lexer1_1.TOKEN_IGNORED);
return str;
case exports.TOKEN_QUOTE:
lexer.NextTokenIs(exports.TOKEN_QUOTE); // 这里已经吃掉一个单个双引号了
str = lexer.scanBeforeToken(lexer1_1.tokenNameMap[exports.TOKEN_QUOTE]); // 这里就会成这样了 eg: aa"后面其他字符串
lexer.NextTokenIs(exports.TOKEN_QUOTE);
lexer.LookAheadAndSkip(exports.TOKEN_IGNORED);
case lexer1_1.TOKEN_QUOTE:
lexer.NextTokenIs(lexer1_1.TOKEN_QUOTE); // 这里已经吃掉一个单个双引号了
str = lexer.scanBeforeToken(lexer1_1.tokenNameMap[lexer1_1.TOKEN_QUOTE]); // 这里就会成这样了 eg: aa"后面其他字符串
lexer.NextTokenIs(lexer1_1.TOKEN_QUOTE);
lexer.LookAheadAndSkip(lexer1_1.TOKEN_IGNORED);
return str;
default:
return "";
Expand All @@ -113,7 +112,7 @@ exports.parseString = parseString;
function parse(code) {
let lexer = lexer1_1.NewLexer(code);
let sourceCode = parseSourceCode(lexer);
lexer.NextTokenIs(exports.TOKEN_EOF);
lexer.NextTokenIs(lexer1_1.TOKEN_EOF);
// console.log(JSON.stringify(sourceCode), 'sourceCode')
return sourceCode;
}
Expand Down
Loading

0 comments on commit be169ae

Please sign in to comment.