Skip to content

Commit

Permalink
fix: Preliminary fix of Expressions syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
liulinboyi committed Mar 4, 2021
1 parent 3445a2b commit 5fb8f8f
Show file tree
Hide file tree
Showing 7 changed files with 265 additions and 18 deletions.
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,23 @@ Integer ::= [0-9]+
Number ::= Integer Ignored
String ::= '"' '"' Ignored | '"' StringCharacter '"' Ignored
Variable ::= "$" Name Ignored // 变量
Assignment ::= Variable Ignored '=' Ignored ( String | Number | Variable | BinaryExpression) Ignored
Assignment ::= Variable Ignored '=' Ignored ( String | Number | Variable | Expressions) Ignored
Print ::= "print" "(" Ignored Variable Ignored ")" Ignored
Statement ::= Print | Assignment
SourceCode ::= Statement+
Comment ::= Ignored "#" SourceCharacter // 注释
BinaryExpression::= (Variable | Number) Ignored Operator Ignored (Variable | Number)
Operator ::= "+" | "-" | "*" | "/" | ">" | "<" | "==" | ">=" | "<="
BinaryExpressions ::= (BinaryExpression Operator)+ Ignored (Variable | Number) // eg: 1: (2 + 1 +) 3 2: ((2 + 1 +) (5 + 6 -)) 3
// BinaryExpression::= (Variable | Number) Ignored Operator1 Ignored (Variable | Number)
Compare ::= ">" | "<" | "==" | ">=" | "<="
Operator1 ::= "+" | "-"
Operator2 ::= "*" | "/"
Expressions ::= Term Expressions_tail
Expressions_tail ::= (Operator1 Term)? // 0个或一个
Term ::= Factor Term_tail
Term_tail ::= (Operator2 Factor)? // 0个或一个
Factor ::= Number | "(" Expressions ")"
FunctionDeclaration ::= "func" Ignored Name Ignored "(" Variable ("," Variable)* ")" BlockStatement // eg: 1: func foo ($a) {} 2: func foo ($a[,$b][,$c]) {} ("," Variable)*这部分是一个或多个
BlockStatement ::= "{" Ignored (IfStatement | CallFunction | Print | Assignment | ReturnStatement ) Ignored "}"
ReturnStatement ::= "return" (BinaryExpression | Variable)
ReturnStatement ::= "return" (Expressions | Variable)
CallFunction ::= Name "(" (Variable | Number) ("," (Variable | Number))* ")" Ignored
IfStatement ::= "if" Ignored "(" Variable Ignored Operator Ignored Variable ")" Ignored BlockStatement Ignored "else" Ignored BlockStatement Ignored
Expand Down
2 changes: 2 additions & 0 deletions demo/hello-world-11.pineapple
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
$a = 1 + 2 + 3
print($a)
120 changes: 117 additions & 3 deletions dist/src/parser/Assignment.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseBinaryExpression = exports.parseAssignment = exports.Assignment = exports.Identifier = exports.Literal = void 0;
exports.parseBinaryExpression = exports.Factor = exports.Trem_tail = exports.Trem = exports.Expression_tail = exports.Expressions = exports.parseAssignment = exports.Assignment = exports.Identifier = exports.Literal = void 0;
const lexer1_1 = require("../lexer1");
const parser_1 = require("../parser");
const Expression_1 = require("./Expression");
Expand Down Expand Up @@ -51,6 +51,7 @@ function parseAssignment(lexer) {
const tokenType = lexer.LookAhead().tokenType;
// 如果后面仍是$
if (tokenType === lexer1_1.TOKEN_VAR_PREFIX) {
// 需要Expressions处理
const Variable = parser_1.parseVariable(lexer); // 标识符,这里面会把邻近的空格回车删掉
const identifier = new Identifier(Variable.Name);
VariableDeclarator.init = identifier;
Expand All @@ -75,8 +76,20 @@ function parseAssignment(lexer) {
assignment.type = "VariableDeclaration";
}
else if (tokenType === lexer1_1.NUMBER) {
const literial = new Literal(parser_1.parseNumber(lexer)); // 这里面会把邻近的空格回车删掉
VariableDeclarator.init = literial;
// 需要Expressions处理
let ex = new BinaryExpression('');
const lineNumber = lexer.GetLineNum();
while (lexer.GetLineNum() === lineNumber) {
const expr = Expressions(lexer, ex);
ex = expr;
// ex.left = expr;
// let ahead = lexer.LookAhead()
// ex.operator = ahead.token
console.log(expr);
}
console.log(ex);
// const literial = new Literal(parseNumber(lexer)) // 这里面会把邻近的空格回车删掉
VariableDeclarator.init = ex;
assignment.type = "VariableDeclaration";
}
else {
Expand All @@ -99,6 +112,107 @@ function parseAssignment(lexer) {
}
}
exports.parseAssignment = parseAssignment;
// $a = $b + $c + $d
// $a = 1 + 2 + 5
// $a = 1 + $b + $c
function Expressions(lexer, expr) {
let value = Trem(lexer, expr);
return Expression_tail(lexer, value ? value : expr);
}
exports.Expressions = Expressions;
function Expression_tail(lexer, value) {
let ahead = lexer.LookAhead();
if (ahead.token === "+") {
if (value instanceof BinaryExpression) {
value.operator = "+";
}
lexer.NextTokenIs(lexer1_1.Operator);
const expression = new BinaryExpression("+");
expression.left = value;
expression.right = Trem(lexer);
return expression;
}
else if (ahead.token === "-") {
if (value instanceof BinaryExpression) {
value.operator = "-";
}
lexer.NextTokenIs(lexer1_1.Operator);
const expression = new BinaryExpression("-");
expression.left = value;
expression.right = Trem(lexer);
return expression;
}
else {
lexer.isIgnored();
return value;
}
}
exports.Expression_tail = Expression_tail;
function Trem(lexer, expr) {
let value = Factor(lexer, expr);
return Trem_tail(lexer, value);
}
exports.Trem = Trem;
function Trem_tail(lexer, value) {
let ahead = lexer.LookAhead();
if (ahead.token === "*") {
lexer.NextTokenIs(lexer1_1.Operator);
const expression = new BinaryExpression("*");
expression.left = value;
expression.right = Factor(lexer);
return expression;
}
else if (ahead.token === "/") {
lexer.NextTokenIs(lexer1_1.Operator);
const expression = new BinaryExpression("/");
expression.left = value;
expression.right = Factor(lexer);
return expression;
}
else {
// 如果不进行NextTokenIs,取消缓存,使用lexer.LookAheadAndSkip(TOKEN_IGNORED)不生效
// 只能使用这个lexer.isIgnored() api了
lexer.isIgnored();
return value;
}
}
exports.Trem_tail = Trem_tail;
function Factor(lexer, expr) {
let ahead = lexer.LookAhead();
if (lexer.isNumber(ahead.token)) {
lexer.NextTokenIs(lexer1_1.NUMBER);
lexer.LookAheadAndSkip(lexer1_1.TOKEN_IGNORED);
return new Literal(+ahead.token);
}
else if (ahead.token === "(") {
// (1 + 2)
lexer.NextTokenIs(lexer1_1.TOKEN_LEFT_PAREN);
lexer.LookAheadAndSkip(lexer1_1.TOKEN_IGNORED);
// type: "BinaryExpression",
// left: {
// // type: "Identifier",
// // name: "c"
// },
// operator: lexer.nextToken,
// right: {
// // type: "Identifier",
// // name: "b"
// }
const exp = Expressions(lexer, expr);
lexer.LookAheadAndSkip(lexer1_1.TOKEN_IGNORED);
lexer.NextTokenIs(lexer1_1.TOKEN_RIGHT_PAREN);
return exp;
}
}
exports.Factor = Factor;
class BinaryExpression {
constructor(operator, type = "BinaryExpression", left = {}, right = {}) {
this.type = type;
this.left = left;
this.operator = operator;
this.right = right;
}
}
function parseBinaryExpression(lexer, idAndinit, assignment, leftType) {
const BinaryExpression = {
type: "BinaryExpression",
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-10.pineapple'), { encoding: 'utf-8' });
code = fs.readFileSync(path.resolve(__dirname, '../demo/hello-world-11.pineapple'), { encoding: 'utf-8' });
console.log(code, 'code');
if (code.length > 0) {
Execute(code);
Expand Down
16 changes: 11 additions & 5 deletions src/lexer1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,23 @@ Integer ::= [0-9]+
Number ::= Integer Ignored
String ::= '"' '"' Ignored | '"' StringCharacter '"' Ignored
Variable ::= "$" Name Ignored // 变量
Assignment ::= Variable Ignored '=' Ignored ( String | Number | Variable | BinaryExpression) Ignored
Assignment ::= Variable Ignored '=' Ignored ( String | Number | Variable | Expressions) Ignored
Print ::= "print" "(" Ignored Variable Ignored ")" Ignored
Statement ::= Print | Assignment
SourceCode ::= Statement+
Comment ::= Ignored "#" SourceCharacter // 注释
BinaryExpression::= (Variable | Number) Ignored Operator Ignored (Variable | Number)
Operator ::= "+" | "-" | "*" | "/" | ">" | "<" | "==" | ">=" | "<="
BinaryExpressions ::= (BinaryExpression Operator)+ Ignored (Variable | Number) // eg: 1: (2 + 1 +) 3 2: ((2 + 1 +) (5 + 6 -)) 3
// BinaryExpression::= (Variable | Number) Ignored Operator1 Ignored (Variable | Number)
Compare ::= ">" | "<" | "==" | ">=" | "<="
Operator1 ::= "+" | "-"
Operator2 ::= "*" | "/"
Expressions ::= Term Expressions_tail
Expressions_tail ::= (Operator1 Term)? // 0个或一个
Term ::= Factor Term_tail
Term_tail ::= (Operator2 Factor)? // 0个或一个
Factor ::= Number | "(" Expressions ")"
FunctionDeclaration ::= "func" Ignored Name Ignored "(" Variable ("," Variable)* ")" BlockStatement // eg: 1: func foo ($a) {} 2: func foo ($a[,$b][,$c]) {} ("," Variable)*这部分是一个或多个
BlockStatement ::= "{" Ignored (IfStatement | CallFunction | Print | Assignment | ReturnStatement ) Ignored "}"
ReturnStatement ::= "return" (BinaryExpression | Variable)
ReturnStatement ::= "return" (Expressions | Variable)
CallFunction ::= Name "(" (Variable | Number) ("," (Variable | Number))* ")" Ignored
IfStatement ::= "if" Ignored "(" Variable Ignored Operator Ignored Variable ")" Ignored BlockStatement Ignored "else" Ignored BlockStatement Ignored
Expand Down
125 changes: 122 additions & 3 deletions src/parser/Assignment.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Variable } from "../definition";
import { Lexer, NUMBER, Operator, tokenNameMap, Tokens, TOKEN_EQUAL, TOKEN_IGNORED, TOKEN_NAME, TOKEN_VAR_PREFIX } from "../lexer1";
import { INTERGER, Lexer, NUMBER, Operator, tokenNameMap, Tokens, TOKEN_EQUAL, TOKEN_IGNORED, TOKEN_LEFT_PAREN, TOKEN_NAME, TOKEN_RIGHT_PAREN, TOKEN_VAR_PREFIX } from "../lexer1";
import { parseNumber, parseString, parseVariable } from "../parser";
import { parseExpression } from "./Expression";

Expand Down Expand Up @@ -75,6 +75,7 @@ export function parseAssignment(lexer: Lexer) {

// 如果后面仍是$
if (tokenType === TOKEN_VAR_PREFIX) {
// 需要Expressions处理
const Variable = parseVariable(lexer) // 标识符,这里面会把邻近的空格回车删掉
const identifier = new Identifier(Variable.Name);
VariableDeclarator.init = identifier
Expand All @@ -98,8 +99,20 @@ export function parseAssignment(lexer: Lexer) {
VariableDeclarator.init = expression.expression
assignment.type = "VariableDeclaration"
} else if (tokenType === NUMBER) {
const literial = new Literal(parseNumber(lexer)) // 这里面会把邻近的空格回车删掉
VariableDeclarator.init = literial
// 需要Expressions处理
let ex = new BinaryExpression('')
const lineNumber = lexer.GetLineNum()
while (lexer.GetLineNum() === lineNumber) {
const expr = Expressions(lexer, ex)
ex = expr
// ex.left = expr;
// let ahead = lexer.LookAhead()
// ex.operator = ahead.token
console.log(expr)
}
console.log(ex)
// const literial = new Literal(parseNumber(lexer)) // 这里面会把邻近的空格回车删掉
VariableDeclarator.init = ex
assignment.type = "VariableDeclaration"
} else {
const literial = new Literal(parseString(lexer)) // 这里面会把邻近的空格回车删掉
Expand All @@ -123,6 +136,112 @@ export function parseAssignment(lexer: Lexer) {
}
}

// $a = $b + $c + $d
// $a = 1 + 2 + 5
// $a = 1 + $b + $c

export function Expressions(lexer: Lexer, expr: any) {
let value = Trem(lexer, expr)
return Expression_tail(lexer, value ? value : expr)
}

export function Expression_tail(lexer: Lexer, value: any) {
let ahead = lexer.LookAhead()
if (ahead.token === "+") {
if (value instanceof BinaryExpression) {
value.operator = "+"
}
lexer.NextTokenIs(Operator)
const expression = new BinaryExpression("+")
expression.left = value;
expression.right = Trem(lexer)
return expression
} else if (ahead.token === "-") {
if (value instanceof BinaryExpression) {
value.operator = "-"
}
lexer.NextTokenIs(Operator)
const expression = new BinaryExpression("-")
expression.left = value;
expression.right = Trem(lexer)
return expression
} else {
lexer.isIgnored()
return value
}
}

export function Trem(lexer: Lexer, expr?: any) {
let value = Factor(lexer, expr)
return Trem_tail(lexer, value)
}

export function Trem_tail(lexer: Lexer, value: any) {
let ahead = lexer.LookAhead()
if (ahead.token === "*") {
lexer.NextTokenIs(Operator)
const expression = new BinaryExpression("*")
expression.left = value;
expression.right = Factor(lexer)
return expression
} else if (ahead.token === "/") {
lexer.NextTokenIs(Operator)
const expression = new BinaryExpression("/")
expression.left = value;
expression.right = Factor(lexer)
return expression
} else {
// 如果不进行NextTokenIs,取消缓存,使用lexer.LookAheadAndSkip(TOKEN_IGNORED)不生效
// 只能使用这个lexer.isIgnored() api了
lexer.isIgnored()
return value
}
}

export function Factor(lexer: Lexer, expr?: any) {
let ahead = lexer.LookAhead()
if (lexer.isNumber(ahead.token)) {
lexer.NextTokenIs(NUMBER)
lexer.LookAheadAndSkip(TOKEN_IGNORED)
return new Literal(+ahead.token)
} else if (ahead.token === "(") {
// (1 + 2)
lexer.NextTokenIs(TOKEN_LEFT_PAREN)
lexer.LookAheadAndSkip(TOKEN_IGNORED)
// type: "BinaryExpression",
// left: {
// // type: "Identifier",
// // name: "c"
// },
// operator: lexer.nextToken,
// right: {
// // type: "Identifier",
// // name: "b"
// }
const exp: any = Expressions(lexer, expr)
lexer.LookAheadAndSkip(TOKEN_IGNORED)
lexer.NextTokenIs(TOKEN_RIGHT_PAREN)

return exp
}
}

interface BinaryExpression {
type?: string,
left: any,
operator?: any,
right?: any
}

class BinaryExpression {
constructor(operator: string, type = "BinaryExpression", left = {}, right = {}) {
this.type = type;
this.left = left;
this.operator = operator;
this.right = right;
}
}

export function parseBinaryExpression(lexer: Lexer, idAndinit: { init: Literal | Identifier, id: Identifier }, assignment: Assignment, leftType: string) {
const BinaryExpression: {
type: string,
Expand Down
2 changes: 1 addition & 1 deletion 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-10.pineapple'), {encoding: 'utf-8'})
code = fs.readFileSync(path.resolve(__dirname, '../demo/hello-world-11.pineapple'), {encoding: 'utf-8'})
console.log(code, 'code')
if (code.length > 0) {
Execute(code)
Expand Down

0 comments on commit 5fb8f8f

Please sign in to comment.