add member expression
This commit is contained in:
@ -1350,4 +1350,174 @@ describe('testing pipe operator special', () => {
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
test('object memberExpression simple', () => {
|
||||||
|
const code = `const prop = yo.one.two`
|
||||||
|
const tokens = lexer(code)
|
||||||
|
const { body } = abstractSyntaxTree(tokens)
|
||||||
|
expect(body).toEqual([
|
||||||
|
{
|
||||||
|
type: 'VariableDeclaration',
|
||||||
|
start: 0,
|
||||||
|
end: 23,
|
||||||
|
kind: 'const',
|
||||||
|
declarations: [
|
||||||
|
{
|
||||||
|
type: 'VariableDeclarator',
|
||||||
|
start: 6,
|
||||||
|
end: 23,
|
||||||
|
id: {
|
||||||
|
type: 'Identifier',
|
||||||
|
start: 6,
|
||||||
|
end: 10,
|
||||||
|
name: 'prop',
|
||||||
|
},
|
||||||
|
init: {
|
||||||
|
type: 'MemberExpression',
|
||||||
|
start: 13,
|
||||||
|
end: 23,
|
||||||
|
computed: false,
|
||||||
|
object: {
|
||||||
|
type: 'MemberExpression',
|
||||||
|
start: 13,
|
||||||
|
end: 19,
|
||||||
|
computed: false,
|
||||||
|
object: {
|
||||||
|
type: 'Identifier',
|
||||||
|
start: 13,
|
||||||
|
end: 15,
|
||||||
|
name: 'yo',
|
||||||
|
},
|
||||||
|
property: {
|
||||||
|
type: 'Identifier',
|
||||||
|
start: 16,
|
||||||
|
end: 19,
|
||||||
|
name: 'one',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
property: {
|
||||||
|
type: 'Identifier',
|
||||||
|
start: 20,
|
||||||
|
end: 23,
|
||||||
|
name: 'two',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
test('object memberExpression with square braces', () => {
|
||||||
|
const code = `const prop = yo.one["two"]`
|
||||||
|
const tokens = lexer(code)
|
||||||
|
const { body } = abstractSyntaxTree(tokens)
|
||||||
|
expect(body).toEqual([
|
||||||
|
{
|
||||||
|
type: 'VariableDeclaration',
|
||||||
|
start: 0,
|
||||||
|
end: 26,
|
||||||
|
kind: 'const',
|
||||||
|
declarations: [
|
||||||
|
{
|
||||||
|
type: 'VariableDeclarator',
|
||||||
|
start: 6,
|
||||||
|
end: 26,
|
||||||
|
id: {
|
||||||
|
type: 'Identifier',
|
||||||
|
start: 6,
|
||||||
|
end: 10,
|
||||||
|
name: 'prop',
|
||||||
|
},
|
||||||
|
init: {
|
||||||
|
type: 'MemberExpression',
|
||||||
|
start: 13,
|
||||||
|
end: 26,
|
||||||
|
computed: false,
|
||||||
|
object: {
|
||||||
|
type: 'MemberExpression',
|
||||||
|
start: 13,
|
||||||
|
end: 19,
|
||||||
|
computed: false,
|
||||||
|
object: {
|
||||||
|
type: 'Identifier',
|
||||||
|
start: 13,
|
||||||
|
end: 15,
|
||||||
|
name: 'yo',
|
||||||
|
},
|
||||||
|
property: {
|
||||||
|
type: 'Identifier',
|
||||||
|
start: 16,
|
||||||
|
end: 19,
|
||||||
|
name: 'one',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
property: {
|
||||||
|
type: 'Literal',
|
||||||
|
start: 20,
|
||||||
|
end: 25,
|
||||||
|
value: 'two',
|
||||||
|
raw: '"two"',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
test('object memberExpression with two square braces literal and identifier', () => {
|
||||||
|
const code = `const prop = yo["one"][two]`
|
||||||
|
const tokens = lexer(code)
|
||||||
|
const { body } = abstractSyntaxTree(tokens)
|
||||||
|
expect(body).toEqual([
|
||||||
|
{
|
||||||
|
type: 'VariableDeclaration',
|
||||||
|
start: 0,
|
||||||
|
end: 27,
|
||||||
|
kind: 'const',
|
||||||
|
declarations: [
|
||||||
|
{
|
||||||
|
type: 'VariableDeclarator',
|
||||||
|
start: 6,
|
||||||
|
end: 27,
|
||||||
|
id: {
|
||||||
|
type: 'Identifier',
|
||||||
|
start: 6,
|
||||||
|
end: 10,
|
||||||
|
name: 'prop',
|
||||||
|
},
|
||||||
|
init: {
|
||||||
|
type: 'MemberExpression',
|
||||||
|
start: 13,
|
||||||
|
end: 27,
|
||||||
|
computed: true,
|
||||||
|
object: {
|
||||||
|
type: 'MemberExpression',
|
||||||
|
start: 13,
|
||||||
|
end: 22,
|
||||||
|
computed: false,
|
||||||
|
object: {
|
||||||
|
type: 'Identifier',
|
||||||
|
start: 13,
|
||||||
|
end: 15,
|
||||||
|
name: 'yo',
|
||||||
|
},
|
||||||
|
property: {
|
||||||
|
type: 'Literal',
|
||||||
|
start: 16,
|
||||||
|
end: 21,
|
||||||
|
value: 'one',
|
||||||
|
raw: '"one"',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
property: {
|
||||||
|
type: 'Identifier',
|
||||||
|
start: 23,
|
||||||
|
end: 26,
|
||||||
|
name: 'two',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -290,6 +290,7 @@ export type Value =
|
|||||||
| PipeSubstitution
|
| PipeSubstitution
|
||||||
| ArrayExpression
|
| ArrayExpression
|
||||||
| ObjectExpression
|
| ObjectExpression
|
||||||
|
| MemberExpression
|
||||||
|
|
||||||
function makeValue(
|
function makeValue(
|
||||||
tokens: Token[],
|
tokens: Token[],
|
||||||
@ -331,8 +332,16 @@ function makeValue(
|
|||||||
lastIndex: arrExp.lastIndex,
|
lastIndex: arrExp.lastIndex,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentToken.type === 'word' && nextToken.type === 'period') {
|
if (
|
||||||
// TODO object access
|
currentToken.type === 'word' &&
|
||||||
|
(nextToken.type === 'period' ||
|
||||||
|
(nextToken.type === 'brace' && nextToken.value === '['))
|
||||||
|
) {
|
||||||
|
const memberExpression = makeMemberExpression(tokens, index)
|
||||||
|
return {
|
||||||
|
value: memberExpression.expression,
|
||||||
|
lastIndex: memberExpression.lastIndex,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (currentToken.type === 'word') {
|
if (currentToken.type === 'word') {
|
||||||
const identifier = makeIdentifier(tokens, index)
|
const identifier = makeIdentifier(tokens, index)
|
||||||
@ -615,6 +624,100 @@ function makeObjectProperties(
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MemberExpression extends GeneralStatement {
|
||||||
|
type: 'MemberExpression'
|
||||||
|
object: MemberExpression | Identifier
|
||||||
|
property: Identifier | Literal
|
||||||
|
computed: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeMemberExpression(
|
||||||
|
tokens: Token[],
|
||||||
|
index: number
|
||||||
|
): { expression: MemberExpression; lastIndex: number } {
|
||||||
|
const currentToken = tokens[index]
|
||||||
|
const keysInfo = collectObjectKeys(tokens, index)
|
||||||
|
const lastKey = keysInfo[keysInfo.length - 1]
|
||||||
|
const firstKey = keysInfo.shift()
|
||||||
|
if (!firstKey) throw new Error('Expected a key')
|
||||||
|
const root = makeIdentifier(tokens, index)
|
||||||
|
let memberExpression: MemberExpression = {
|
||||||
|
type: 'MemberExpression',
|
||||||
|
start: currentToken.start,
|
||||||
|
end: tokens[firstKey.index].end,
|
||||||
|
object: root,
|
||||||
|
property: firstKey.key,
|
||||||
|
computed: firstKey.computed,
|
||||||
|
}
|
||||||
|
keysInfo.forEach(({ key, computed, index }, i) => {
|
||||||
|
const endToken = tokens[index]
|
||||||
|
memberExpression = {
|
||||||
|
type: 'MemberExpression',
|
||||||
|
start: currentToken.start,
|
||||||
|
end: endToken.end,
|
||||||
|
object: memberExpression,
|
||||||
|
property: key,
|
||||||
|
computed,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
expression: memberExpression,
|
||||||
|
lastIndex: lastKey.index,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ObjectKeyInfo {
|
||||||
|
key: Identifier | Literal
|
||||||
|
index: number
|
||||||
|
computed: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
function collectObjectKeys(
|
||||||
|
tokens: Token[],
|
||||||
|
index: number,
|
||||||
|
previousKeys: ObjectKeyInfo[] = []
|
||||||
|
): ObjectKeyInfo[] {
|
||||||
|
const nextToken = nextMeaningfulToken(tokens, index)
|
||||||
|
const periodOrOpeningBracketToken =
|
||||||
|
nextToken?.token?.type === 'brace' && nextToken.token.value === ']'
|
||||||
|
? nextMeaningfulToken(tokens, nextToken.index)
|
||||||
|
: nextToken
|
||||||
|
if (
|
||||||
|
periodOrOpeningBracketToken?.token?.type !== 'period' &&
|
||||||
|
periodOrOpeningBracketToken?.token?.type !== 'brace'
|
||||||
|
) {
|
||||||
|
return previousKeys
|
||||||
|
}
|
||||||
|
const keyToken = nextMeaningfulToken(
|
||||||
|
tokens,
|
||||||
|
periodOrOpeningBracketToken.index
|
||||||
|
)
|
||||||
|
const nextPeriodOrOpeningBracketToken = nextMeaningfulToken(
|
||||||
|
tokens,
|
||||||
|
keyToken.index
|
||||||
|
)
|
||||||
|
const isBraced =
|
||||||
|
nextPeriodOrOpeningBracketToken?.token?.type === 'brace' &&
|
||||||
|
nextPeriodOrOpeningBracketToken?.token?.value === ']'
|
||||||
|
const endIndex = isBraced
|
||||||
|
? nextPeriodOrOpeningBracketToken.index
|
||||||
|
: keyToken.index
|
||||||
|
const key =
|
||||||
|
keyToken.token.type === 'word'
|
||||||
|
? makeIdentifier(tokens, keyToken.index)
|
||||||
|
: makeLiteral(tokens, keyToken.index)
|
||||||
|
const computed = isBraced && keyToken.token.type === 'word' ? true : false
|
||||||
|
return collectObjectKeys(tokens, keyToken.index, [
|
||||||
|
...previousKeys,
|
||||||
|
{
|
||||||
|
key,
|
||||||
|
index: endIndex,
|
||||||
|
computed,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
export interface BinaryExpression extends GeneralStatement {
|
export interface BinaryExpression extends GeneralStatement {
|
||||||
type: 'BinaryExpression'
|
type: 'BinaryExpression'
|
||||||
operator: string
|
operator: string
|
||||||
|
@ -206,6 +206,18 @@ show(mySketch)
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
it('execute memberExpression', () => {
|
||||||
|
const code = ["const yo = {a: {b: '123'}}", "const myVar = yo.a['b']"].join(
|
||||||
|
'\n'
|
||||||
|
)
|
||||||
|
const { root } = exe(code)
|
||||||
|
expect(root).toEqual({
|
||||||
|
yo: {
|
||||||
|
a: { b: '123' },
|
||||||
|
},
|
||||||
|
myVar: '123',
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
BinaryExpression,
|
BinaryExpression,
|
||||||
PipeExpression,
|
PipeExpression,
|
||||||
ObjectExpression,
|
ObjectExpression,
|
||||||
|
MemberExpression,
|
||||||
} from './abstractSyntaxTree'
|
} from './abstractSyntaxTree'
|
||||||
import { Path, Transform, SketchGeo, sketchFns, ExtrudeGeo } from './sketch'
|
import { Path, Transform, SketchGeo, sketchFns, ExtrudeGeo } from './sketch'
|
||||||
import { BufferGeometry, Quaternion, Vector3 } from 'three'
|
import { BufferGeometry, Quaternion, Vector3 } from 'three'
|
||||||
@ -116,6 +117,11 @@ export const executor = (
|
|||||||
})
|
})
|
||||||
return executor(fnInit.body, fnMemory, { bodyType: 'block' }).return
|
return executor(fnInit.body, fnMemory, { bodyType: 'block' }).return
|
||||||
}
|
}
|
||||||
|
} else if (declaration.init.type === 'MemberExpression') {
|
||||||
|
_programMemory.root[variableName] = getMemberExpressionResult(
|
||||||
|
declaration.init,
|
||||||
|
_programMemory
|
||||||
|
)
|
||||||
} else if (declaration.init.type === 'CallExpression') {
|
} else if (declaration.init.type === 'CallExpression') {
|
||||||
const functionName = declaration.init.callee.name
|
const functionName = declaration.init.callee.name
|
||||||
const fnArgs = declaration.init.arguments.map((arg) => {
|
const fnArgs = declaration.init.arguments.map((arg) => {
|
||||||
@ -189,6 +195,10 @@ export const executor = (
|
|||||||
functionName
|
functionName
|
||||||
](...fnArgs)
|
](...fnArgs)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
'Unsupported declaration type: ' + declaration.init.type
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else if (statement.type === 'ExpressionStatement') {
|
} else if (statement.type === 'ExpressionStatement') {
|
||||||
@ -240,6 +250,22 @@ export const executor = (
|
|||||||
return _programMemory
|
return _programMemory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getMemberExpressionResult(
|
||||||
|
expression: MemberExpression,
|
||||||
|
programMemory: ProgramMemory
|
||||||
|
) {
|
||||||
|
const propertyName = (
|
||||||
|
expression.property.type === 'Identifier'
|
||||||
|
? expression.property.name
|
||||||
|
: expression.property.value
|
||||||
|
) as any
|
||||||
|
const object: any =
|
||||||
|
expression.object.type === 'MemberExpression'
|
||||||
|
? getMemberExpressionResult(expression.object, programMemory)
|
||||||
|
: programMemory.root[expression.object.name]
|
||||||
|
return object[propertyName]
|
||||||
|
}
|
||||||
|
|
||||||
function getBinaryExpressionResult(
|
function getBinaryExpressionResult(
|
||||||
expression: BinaryExpression,
|
expression: BinaryExpression,
|
||||||
programMemory: ProgramMemory
|
programMemory: ProgramMemory
|
||||||
@ -407,6 +433,11 @@ function executeObjectExpression(
|
|||||||
)
|
)
|
||||||
} else if (property.value.type === 'Identifier') {
|
} else if (property.value.type === 'Identifier') {
|
||||||
obj[property.key.name] = _programMemory.root[property.value.name]
|
obj[property.key.name] = _programMemory.root[property.value.name]
|
||||||
|
} else if (property.value.type === 'ObjectExpression') {
|
||||||
|
obj[property.key.name] = executeObjectExpression(
|
||||||
|
_programMemory,
|
||||||
|
property.value
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unexpected property type ${property.value.type} in object expression`
|
`Unexpected property type ${property.value.type} in object expression`
|
||||||
|
@ -140,6 +140,16 @@ const yo = {
|
|||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code.trim())
|
expect(recasted).toBe(code.trim())
|
||||||
})
|
})
|
||||||
|
it('recast object execution with member expression', () => {
|
||||||
|
const code = `const yo = { a: { b: { c: '123' } } }
|
||||||
|
const key = 'c'
|
||||||
|
const myVar = yo.a['b'][key]
|
||||||
|
const key2 = 'b'
|
||||||
|
const myVar2 = yo['a'][key2].c`
|
||||||
|
const { ast } = code2ast(code)
|
||||||
|
const recasted = recast(ast)
|
||||||
|
expect(recasted).toBe(code.trim())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
SketchExpression,
|
SketchExpression,
|
||||||
ArrayExpression,
|
ArrayExpression,
|
||||||
ObjectExpression,
|
ObjectExpression,
|
||||||
|
MemberExpression,
|
||||||
} from './abstractSyntaxTree'
|
} from './abstractSyntaxTree'
|
||||||
|
|
||||||
export function recast(
|
export function recast(
|
||||||
@ -155,6 +156,23 @@ ${recast(expression.body, '', indentation + ' ')}
|
|||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function recastMemberExpression(
|
||||||
|
expression: MemberExpression,
|
||||||
|
indentation: string
|
||||||
|
): string {
|
||||||
|
// TODO handle breaking into multiple lines if too long
|
||||||
|
let keyString =
|
||||||
|
expression.computed && expression.property.type === 'Identifier'
|
||||||
|
? `[${expression.property.name}]`
|
||||||
|
: expression.property.type !== 'Identifier'
|
||||||
|
? `[${expression.property.raw}]`
|
||||||
|
: `.${expression.property.name}`
|
||||||
|
if (expression.object.type === 'MemberExpression') {
|
||||||
|
return recastMemberExpression(expression.object, indentation) + keyString
|
||||||
|
}
|
||||||
|
return expression.object.name + keyString
|
||||||
|
}
|
||||||
|
|
||||||
function recastValue(node: Value, indentation = ''): string {
|
function recastValue(node: Value, indentation = ''): string {
|
||||||
if (node.type === 'BinaryExpression') {
|
if (node.type === 'BinaryExpression') {
|
||||||
return recastBinaryExpression(node)
|
return recastBinaryExpression(node)
|
||||||
@ -162,6 +180,8 @@ function recastValue(node: Value, indentation = ''): string {
|
|||||||
return recastArrayExpression(node, indentation)
|
return recastArrayExpression(node, indentation)
|
||||||
} else if (node.type === 'ObjectExpression') {
|
} else if (node.type === 'ObjectExpression') {
|
||||||
return recastObjectExpression(node, indentation)
|
return recastObjectExpression(node, indentation)
|
||||||
|
} else if (node.type === 'MemberExpression') {
|
||||||
|
return recastMemberExpression(node, indentation)
|
||||||
} else if (node.type === 'Literal') {
|
} else if (node.type === 'Literal') {
|
||||||
return recastLiteral(node)
|
return recastLiteral(node)
|
||||||
} else if (node.type === 'FunctionExpression') {
|
} else if (node.type === 'FunctionExpression') {
|
||||||
|
@ -366,6 +366,67 @@ describe('testing lexer', () => {
|
|||||||
"brace '}' from 24 to 25",
|
"brace '}' from 24 to 25",
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
it('testing object property access', () => {
|
||||||
|
const result = stringSummaryLexer(`const yo = {key: 'value'}
|
||||||
|
const prop = yo.key
|
||||||
|
const prop2 = yo['key']
|
||||||
|
const key = 'key'
|
||||||
|
const prop3 = yo[key]`)
|
||||||
|
expect(result).toEqual([
|
||||||
|
"word 'const' from 0 to 5",
|
||||||
|
"whitespace ' ' from 5 to 6",
|
||||||
|
"word 'yo' from 6 to 8",
|
||||||
|
"whitespace ' ' from 8 to 9",
|
||||||
|
"operator '=' from 9 to 10",
|
||||||
|
"whitespace ' ' from 10 to 11",
|
||||||
|
"brace '{' from 11 to 12",
|
||||||
|
"word 'key' from 12 to 15",
|
||||||
|
"colon ':' from 15 to 16",
|
||||||
|
"whitespace ' ' from 16 to 17",
|
||||||
|
"string ''value'' from 17 to 24",
|
||||||
|
"brace '}' from 24 to 25",
|
||||||
|
"whitespace '\n' from 25 to 26",
|
||||||
|
"word 'const' from 26 to 31",
|
||||||
|
"whitespace ' ' from 31 to 32",
|
||||||
|
"word 'prop' from 32 to 36",
|
||||||
|
"whitespace ' ' from 36 to 37",
|
||||||
|
"operator '=' from 37 to 38",
|
||||||
|
"whitespace ' ' from 38 to 39",
|
||||||
|
"word 'yo' from 39 to 41",
|
||||||
|
"period '.' from 41 to 42",
|
||||||
|
"word 'key' from 42 to 45",
|
||||||
|
"whitespace '\n' from 45 to 46",
|
||||||
|
"word 'const' from 46 to 51",
|
||||||
|
"whitespace ' ' from 51 to 52",
|
||||||
|
"word 'prop2' from 52 to 57",
|
||||||
|
"whitespace ' ' from 57 to 58",
|
||||||
|
"operator '=' from 58 to 59",
|
||||||
|
"whitespace ' ' from 59 to 60",
|
||||||
|
"word 'yo' from 60 to 62",
|
||||||
|
"brace '[' from 62 to 63",
|
||||||
|
"string ''key'' from 63 to 68",
|
||||||
|
"brace ']' from 68 to 69",
|
||||||
|
"whitespace '\n' from 69 to 70",
|
||||||
|
"word 'const' from 70 to 75",
|
||||||
|
"whitespace ' ' from 75 to 76",
|
||||||
|
"word 'key' from 76 to 79",
|
||||||
|
"whitespace ' ' from 79 to 80",
|
||||||
|
"operator '=' from 80 to 81",
|
||||||
|
"whitespace ' ' from 81 to 82",
|
||||||
|
"string ''key'' from 82 to 87",
|
||||||
|
"whitespace '\n' from 87 to 88",
|
||||||
|
"word 'const' from 88 to 93",
|
||||||
|
"whitespace ' ' from 93 to 94",
|
||||||
|
"word 'prop3' from 94 to 99",
|
||||||
|
"whitespace ' ' from 99 to 100",
|
||||||
|
"operator '=' from 100 to 101",
|
||||||
|
"whitespace ' ' from 101 to 102",
|
||||||
|
"word 'yo' from 102 to 104",
|
||||||
|
"brace '[' from 104 to 105",
|
||||||
|
"word 'key' from 105 to 108",
|
||||||
|
"brace ']' from 108 to 109",
|
||||||
|
])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
|
@ -16,6 +16,7 @@ const ARRAY_START = /^\[/
|
|||||||
const ARRAY_END = /^\]/
|
const ARRAY_END = /^\]/
|
||||||
const COMMA = /^,/
|
const COMMA = /^,/
|
||||||
const COLON = /^:/
|
const COLON = /^:/
|
||||||
|
const PERIOD = /^\./
|
||||||
|
|
||||||
export const isNumber = (character: string) => NUMBER.test(character)
|
export const isNumber = (character: string) => NUMBER.test(character)
|
||||||
export const isWhitespace = (character: string) => WHITESPACE.test(character)
|
export const isWhitespace = (character: string) => WHITESPACE.test(character)
|
||||||
@ -30,6 +31,7 @@ export const isArrayStart = (character: string) => ARRAY_START.test(character)
|
|||||||
export const isArrayEnd = (character: string) => ARRAY_END.test(character)
|
export const isArrayEnd = (character: string) => ARRAY_END.test(character)
|
||||||
export const isComma = (character: string) => COMMA.test(character)
|
export const isComma = (character: string) => COMMA.test(character)
|
||||||
export const isColon = (character: string) => COLON.test(character)
|
export const isColon = (character: string) => COLON.test(character)
|
||||||
|
export const isPeriod = (character: string) => PERIOD.test(character)
|
||||||
|
|
||||||
function matchFirst(str: string, regex: RegExp) {
|
function matchFirst(str: string, regex: RegExp) {
|
||||||
const theMatch = str.match(regex)
|
const theMatch = str.match(regex)
|
||||||
@ -49,6 +51,7 @@ export interface Token {
|
|||||||
| 'whitespace'
|
| 'whitespace'
|
||||||
| 'comma'
|
| 'comma'
|
||||||
| 'colon'
|
| 'colon'
|
||||||
|
| 'period'
|
||||||
value: string
|
value: string
|
||||||
start: number
|
start: number
|
||||||
end: number
|
end: number
|
||||||
@ -100,9 +103,10 @@ const returnTokenAtIndex = (str: string, startIndex: number): Token | null => {
|
|||||||
if (isWord(strFromIndex)) {
|
if (isWord(strFromIndex)) {
|
||||||
return makeToken('word', matchFirst(strFromIndex, WORD), startIndex)
|
return makeToken('word', matchFirst(strFromIndex, WORD), startIndex)
|
||||||
}
|
}
|
||||||
if (isColon(strFromIndex)) {
|
if (isColon(strFromIndex))
|
||||||
return makeToken('colon', matchFirst(strFromIndex, COLON), startIndex)
|
return makeToken('colon', matchFirst(strFromIndex, COLON), startIndex)
|
||||||
}
|
if (isPeriod(strFromIndex))
|
||||||
|
return makeToken('period', matchFirst(strFromIndex, PERIOD), startIndex)
|
||||||
if (isWhitespace(strFromIndex)) {
|
if (isWhitespace(strFromIndex)) {
|
||||||
return makeToken(
|
return makeToken(
|
||||||
'whitespace',
|
'whitespace',
|
||||||
|
Reference in New Issue
Block a user