Improved math expressions (#6)
* Improved math expressions Things are in a better state, + - / * work now for basic const var = 5 <operator> 1 Though the current method I'm using to make the ast isn't really going to work for dealing with precedence rules so some refactoring is needed going forward * get complex math expressions working with precedence including parans Node that identifiers are working, call expressions are not, that's a TODO / * % + - are working both other things like exponent and logical operators are also not working. Recasting is the most important thing to implement next * get recasting working for nested binary expressions * clean up
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
import { PathToNode } from './executor'
|
||||
import { Token } from './tokeniser'
|
||||
import { parseExpression } from './astMathExpressions'
|
||||
|
||||
type syntaxType =
|
||||
| 'Program'
|
||||
@ -473,8 +474,7 @@ function makeVariableDeclarators(
|
||||
}
|
||||
}
|
||||
|
||||
export type BinaryPart = Literal | Identifier
|
||||
// | BinaryExpression
|
||||
export type BinaryPart = Literal | Identifier | BinaryExpression
|
||||
// | CallExpression
|
||||
// | MemberExpression
|
||||
// | ArrayExpression
|
||||
@ -764,7 +764,7 @@ export interface BinaryExpression extends GeneralStatement {
|
||||
function makeBinaryPart(
|
||||
tokens: Token[],
|
||||
index: number
|
||||
): { part: BinaryPart; lastIndex: number } {
|
||||
): { part: Literal | Identifier; lastIndex: number } {
|
||||
const currentToken = tokens[index]
|
||||
if (currentToken.type === 'word') {
|
||||
const identifier = makeIdentifier(tokens, index)
|
||||
@ -783,28 +783,43 @@ function makeBinaryPart(
|
||||
throw new Error('Expected a previous BinaryPart if statement to match')
|
||||
}
|
||||
|
||||
export function findEndOfBinaryExpression(
|
||||
tokens: Token[],
|
||||
index: number
|
||||
): number {
|
||||
const currentToken = tokens[index]
|
||||
if (currentToken.type === 'brace' && currentToken.value === '(') {
|
||||
const closingParenthesis = findClosingBrace(tokens, index)
|
||||
const maybeAnotherOperator = nextMeaningfulToken(tokens, closingParenthesis)
|
||||
if (
|
||||
maybeAnotherOperator?.token?.type !== 'operator' ||
|
||||
maybeAnotherOperator?.token?.value === '|>'
|
||||
) {
|
||||
return closingParenthesis
|
||||
}
|
||||
const nextRight = nextMeaningfulToken(tokens, maybeAnotherOperator.index)
|
||||
return findEndOfBinaryExpression(tokens, nextRight.index)
|
||||
}
|
||||
const maybeOperator = nextMeaningfulToken(tokens, index)
|
||||
if (
|
||||
maybeOperator?.token?.type !== 'operator' ||
|
||||
maybeOperator?.token?.value === '|>'
|
||||
) {
|
||||
return index
|
||||
}
|
||||
const nextRight = nextMeaningfulToken(tokens, maybeOperator.index)
|
||||
return findEndOfBinaryExpression(tokens, nextRight.index)
|
||||
}
|
||||
|
||||
function makeBinaryExpression(
|
||||
tokens: Token[],
|
||||
index: number
|
||||
): { expression: BinaryExpression; lastIndex: number } {
|
||||
const currentToken = tokens[index]
|
||||
const { part: left } = makeBinaryPart(tokens, index)
|
||||
const { token: operatorToken, index: operatorIndex } = nextMeaningfulToken(
|
||||
tokens,
|
||||
index
|
||||
)
|
||||
const rightToken = nextMeaningfulToken(tokens, operatorIndex)
|
||||
const { part: right } = makeBinaryPart(tokens, rightToken.index)
|
||||
const endIndex = findEndOfBinaryExpression(tokens, index)
|
||||
const expression = parseExpression(tokens.slice(index, endIndex + 1))
|
||||
return {
|
||||
expression: {
|
||||
type: 'BinaryExpression',
|
||||
start: currentToken.start,
|
||||
end: right.end,
|
||||
left,
|
||||
operator: operatorToken.value,
|
||||
right,
|
||||
},
|
||||
lastIndex: rightToken.index,
|
||||
expression,
|
||||
lastIndex: endIndex,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1296,6 +1311,61 @@ export function findClosingBrace(
|
||||
return findClosingBrace(tokens, index + 1, _braceCount, searchOpeningBrace)
|
||||
}
|
||||
|
||||
// function findOpeningBrace(
|
||||
// tokens: Token[],
|
||||
// index: number,
|
||||
// _braceCount: number = 0,
|
||||
// _searchClosingBrace: string = ''
|
||||
// ): number {
|
||||
// // should be called with the index of the opening brace
|
||||
// const closingBraceMap: { [key: string]: string } = {
|
||||
// ')': '(',
|
||||
// '}': '{',
|
||||
// ']': '[',
|
||||
// }
|
||||
// const currentToken = tokens[index]
|
||||
// let searchClosingBrace = _searchClosingBrace
|
||||
|
||||
// const isFirstCall = !searchClosingBrace && _braceCount === 0
|
||||
// if (isFirstCall) {
|
||||
// searchClosingBrace = currentToken.value
|
||||
// if (![')', '}', ']'].includes(searchClosingBrace)) {
|
||||
// throw new Error(
|
||||
// `expected to be started on a opening brace ( { [, instead found '${searchClosingBrace}'`
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
|
||||
// const foundOpeningBrace =
|
||||
// _braceCount === 1 &&
|
||||
// currentToken.value === closingBraceMap[searchClosingBrace]
|
||||
// const foundAnotherClosingBrace = currentToken.value === searchClosingBrace
|
||||
// const foundAnotherOpeningBrace =
|
||||
// currentToken.value === closingBraceMap[searchClosingBrace]
|
||||
|
||||
// if (foundOpeningBrace) {
|
||||
// return index
|
||||
// }
|
||||
// if (foundAnotherClosingBrace) {
|
||||
// return findOpeningBrace(
|
||||
// tokens,
|
||||
// index - 1,
|
||||
// _braceCount + 1,
|
||||
// searchClosingBrace
|
||||
// )
|
||||
// }
|
||||
// if (foundAnotherOpeningBrace) {
|
||||
// return findOpeningBrace(
|
||||
// tokens,
|
||||
// index - 1,
|
||||
// _braceCount - 1,
|
||||
// searchClosingBrace
|
||||
// )
|
||||
// }
|
||||
// // non-brace token, increment and continue
|
||||
// return findOpeningBrace(tokens, index - 1, _braceCount, searchClosingBrace)
|
||||
// }
|
||||
|
||||
function isCallExpression(tokens: Token[], index: number): number {
|
||||
const currentToken = tokens[index]
|
||||
const veryNextToken = tokens[index + 1] // i.e. no whitespace
|
||||
|
Reference in New Issue
Block a user