Skip to content

Commit

Permalink
式の解析にpratt parsingを導入する (#83)
Browse files Browse the repository at this point in the history
* pratt parsing

* pratt parsing

* update wasm

* update interpreter

* rename token
  • Loading branch information
marihachi committed Aug 21, 2023
1 parent 804f7e2 commit a900fe7
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 133 deletions.
44 changes: 23 additions & 21 deletions src/lib/running/binary-expr.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { UguisuError } from '../misc/errors.js';
import { ArithmeticOperator, EquivalentOperator, LogicalBinaryOperator, OrderingOperator } from '../syntax/node.js';
import { Token } from '../syntax/token.js';
import { createOk, EvalResult } from './result.js';
import {
assertValue,
Expand All @@ -20,10 +21,10 @@ export function evalLogicalBinaryOp(op: LogicalBinaryOperator, left: Value, righ
assertValue(left, 'BoolValue');
assertValue(right, 'BoolValue');
switch (op) {
case '&&': {
case Token.And2: {
return createOk(createBoolValue(left && right));
}
case '||': {
case Token.Or2: {
return createOk(createBoolValue(left || right));
}
}
Expand All @@ -41,10 +42,10 @@ export function evalEquivalentBinaryOp(op: EquivalentOperator, left: Value, righ
left = left as NumberValue;
assertValue(right, 'NumberValue');
switch (op) {
case '==': {
case Token.Eq2: {
return createOk(createBoolValue(left == right));
}
case '!=': {
case Token.NotEq: {
return createOk(createBoolValue(left != right));
}
}
Expand All @@ -54,10 +55,10 @@ export function evalEquivalentBinaryOp(op: EquivalentOperator, left: Value, righ
left = left as BoolValue;
assertValue(right, 'BoolValue');
switch (op) {
case '==': {
case Token.Eq2: {
return createOk(createBoolValue(left == right));
}
case '!=': {
case Token.NotEq: {
return createOk(createBoolValue(left != right));
}
}
Expand All @@ -67,10 +68,10 @@ export function evalEquivalentBinaryOp(op: EquivalentOperator, left: Value, righ
left = left as CharValue;
assertValue(right, 'CharValue');
switch (op) {
case '==': {
case Token.Eq2: {
return createOk(createBoolValue(left == right));
}
case '!=': {
case Token.NotEq: {
return createOk(createBoolValue(left != right));
}
}
Expand All @@ -80,10 +81,10 @@ export function evalEquivalentBinaryOp(op: EquivalentOperator, left: Value, righ
left = left as StringValue;
assertValue(right, 'StringValue');
switch (op) {
case '==': {
case Token.Eq2: {
return createOk(createBoolValue(left == right));
}
case '!=': {
case Token.NotEq: {
return createOk(createBoolValue(left != right));
}
}
Expand All @@ -102,10 +103,10 @@ export function evalEquivalentBinaryOp(op: EquivalentOperator, left: Value, righ
left = left as FunctionValue;
assertValue(right, 'FunctionValue');
switch (op) {
case '==': {
case Token.Eq2: {
return createOk(createBoolValue(equalFunc(left, right)));
}
case '!=': {
case Token.NotEq: {
return createOk(createBoolValue(!equalFunc(left, right)));
}
}
Expand All @@ -128,18 +129,19 @@ export function evalOrderingBinaryOp(op: OrderingOperator, left: Value, right: V
}
switch (getValueKind(left)) {
case 'NumberValue': {
left = left as NumberValue;
assertValue(right, 'NumberValue');
switch (op) {
case '<': {
case Token.LessThan: {
return createOk(createBoolValue(left < right));
}
case '<=': {
case Token.LessThanEq: {
return createOk(createBoolValue(left <= right));
}
case '>': {
case Token.GreaterThan: {
return createOk(createBoolValue(left > right));
}
case '>=': {
case Token.GreaterThanEq: {
return createOk(createBoolValue(left >= right));
}
}
Expand All @@ -161,19 +163,19 @@ export function evalArithmeticBinaryOp(op: ArithmeticOperator, left: Value, righ
assertValue(left, 'NumberValue');
assertValue(right, 'NumberValue');
switch (op) {
case '+': {
case Token.Plus: {
return createOk(createNumberValue(left + right));
}
case '-': {
case Token.Minus: {
return createOk(createNumberValue(left - right));
}
case '*': {
case Token.Asterisk: {
return createOk(createNumberValue(left * right));
}
case '/': {
case Token.Slash: {
return createOk(createNumberValue(left / right));
}
case '%': {
case Token.Percent: {
return createOk(createNumberValue(left % right));
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/lib/running/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
StatementNode,
StepNode
} from '../syntax/node.js';
import { Token } from '../syntax/token.js';
import {
evalArithmeticBinaryOp,
evalEquivalentBinaryOp,
Expand Down Expand Up @@ -388,7 +389,7 @@ function evalExpr(r: RunContext, expr: ExprNode): EvalResult<Value> {
// Logical Operation
assertValue(result.value, 'BoolValue');
switch (expr.operator) {
case '!': {
case Token.Not: {
return createOk(createBoolValue(!result.value));
}
}
Expand Down
21 changes: 11 additions & 10 deletions src/lib/syntax/node.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Token } from './token.js';

export type Pos = [number, number];

export type SyntaxNode =
Expand Down Expand Up @@ -202,8 +204,7 @@ export type UnaryOp = {
export function createUnaryOp(pos: Pos, operator: UnaryOperator, expr: ExprNode): UnaryOp {
return { kind: 'UnaryOp', pos, operator, expr };
}
export type UnaryOperator = LogicalUnaryOperator;
export type LogicalUnaryOperator = '!';
export type UnaryOperator = Token.Not | Token.Plus | Token.Minus;

export type BinaryOp = {
kind: 'BinaryOp',
Expand All @@ -224,29 +225,29 @@ export function createBinaryOp(
export type BinaryOperator =
LogicalBinaryOperator | EquivalentOperator | OrderingOperator | ArithmeticOperator;

export type LogicalBinaryOperator = '||' | '&&';
const logicalBinaryOperators: BinaryOperator[] = ['||', '&&'];
export type LogicalBinaryOperator = Token.Or2 | Token.And2;
const logicalBinaryOperators: BinaryOperator[] = [Token.Or2, Token.And2];

export function isLogicalBinaryOperator(x: BinaryOperator): x is LogicalBinaryOperator {
return logicalBinaryOperators.includes(x);
}

export type EquivalentOperator = '==' | '!=';
const equivalentOperators: BinaryOperator[] = ['==', '!='];
export type EquivalentOperator = Token.Eq2 | Token.NotEq;
const equivalentOperators: BinaryOperator[] = [Token.Eq2, Token.NotEq];

export function isEquivalentOperator(x: BinaryOperator): x is EquivalentOperator {
return equivalentOperators.includes(x);
}

export type OrderingOperator = '<' |'<=' | '>' | '>=';
const orderingOperators: BinaryOperator[] = ['<', '<=', '>', '>='];
export type OrderingOperator = Token.LessThan | Token.LessThanEq | Token.GreaterThan | Token.GreaterThanEq;
const orderingOperators: BinaryOperator[] = [Token.LessThan, Token.LessThanEq, Token.GreaterThan, Token.GreaterThanEq];

export function isOrderingOperator(x: BinaryOperator): x is OrderingOperator {
return orderingOperators.includes(x);
}

export type ArithmeticOperator = '+' | '-' | '*' | '/' | '%';
const arithmeticOperators: BinaryOperator[] = ['+', '-', '*', '/', '%'];
export type ArithmeticOperator = Token.Plus | Token.Minus | Token.Asterisk | Token.Slash | Token.Percent;
const arithmeticOperators: BinaryOperator[] = [Token.Plus, Token.Minus, Token.Asterisk, Token.Slash, Token.Percent];

export function isArithmeticOperator(x: BinaryOperator): x is ArithmeticOperator {
return arithmeticOperators.includes(x);
Expand Down
Loading

0 comments on commit a900fe7

Please sign in to comment.