Parser 2.0 (Major Delezer) #52
|
|
@ -241,6 +241,22 @@ export class Parser {
|
|||
// parse specific nodes
|
||||
//
|
||||
|
||||
// raw determines whether we just want the SyntaxNodes or we want to
|
||||
// wrap them in a PositionalArg
|
||||
arg(raw = false): SyntaxNode {
|
||||
// 'do' is a special function arg - it doesn't need to be wrapped
|
||||
// in parens. otherwise, args are regular value()s
|
||||
const val = this.is($T.Keyword, 'do') ? this.do() : this.value()
|
||||
|
||||
if (raw) {
|
||||
return val
|
||||
} else {
|
||||
const arg = new SyntaxNode('PositionalArg', val.from, val.to)
|
||||
arg.add(val)
|
||||
return arg
|
||||
}
|
||||
}
|
||||
|
||||
// [ 1 2 3 ]
|
||||
array(): SyntaxNode {
|
||||
const open = this.expect($T.OpenBracket)
|
||||
|
|
@ -425,10 +441,7 @@ export class Parser {
|
|||
continue
|
||||
}
|
||||
|
||||
if (this.is($T.NamedArgPrefix))
|
||||
values.push(this.namedArg())
|
||||
else
|
||||
values.push(this.value())
|
||||
values.push(this.is($T.NamedArgPrefix) ? this.namedArg() : this.arg())
|
||||
}
|
||||
|
||||
const close = this.expect($T.CloseBracket)
|
||||
|
|
@ -549,17 +562,8 @@ export class Parser {
|
|||
const ident = fn ?? this.identifier()
|
||||
|
||||
const args: SyntaxNode[] = []
|
||||
while (!this.isExprEnd() && !this.is($T.Operator, '|')) {
|
||||
if (this.is($T.NamedArgPrefix)) {
|
||||
args.push(this.namedArg())
|
||||
} else {
|
||||
// 'do' is the only keyword allowed as a function argument
|
||||
const val = this.is($T.Keyword, 'do') ? this.do() : this.value()
|
||||
const arg = new SyntaxNode('PositionalArg', val.from, val.to)
|
||||
arg.add(val)
|
||||
args.push(arg)
|
||||
}
|
||||
}
|
||||
while (!this.isExprEnd() && !this.is($T.Operator, '|'))
|
||||
args.push(this.is($T.NamedArgPrefix) ? this.namedArg() : this.arg())
|
||||
|
||||
const node = new SyntaxNode('FunctionCall', ident.from, (args.at(-1) || ident).to)
|
||||
node.push(ident, ...args)
|
||||
|
|
@ -669,7 +673,7 @@ export class Parser {
|
|||
// abc= true
|
||||
namedArg(): SyntaxNode {
|
||||
const prefix = SyntaxNode.from(this.expect($T.NamedArgPrefix))
|
||||
const val = this.value()
|
||||
const val = this.arg(true)
|
||||
const node = new SyntaxNode('NamedArg', prefix.from, val.to)
|
||||
return node.push(prefix, val)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,58 @@ describe('calling functions', () => {
|
|||
`)
|
||||
})
|
||||
|
||||
test('call with function', () => {
|
||||
expect(`tail do x: x end`).toMatchTree(`
|
||||
FunctionCall
|
||||
Identifier tail
|
||||
PositionalArg
|
||||
FunctionDef
|
||||
Do do
|
||||
Params
|
||||
Identifier x
|
||||
colon :
|
||||
FunctionCallOrIdentifier
|
||||
Identifier x
|
||||
keyword end
|
||||
`)
|
||||
})
|
||||
|
||||
test('call with arg and function', () => {
|
||||
expect(`tail true do x: x end`).toMatchTree(`
|
||||
FunctionCall
|
||||
Identifier tail
|
||||
PositionalArg
|
||||
Boolean true
|
||||
PositionalArg
|
||||
FunctionDef
|
||||
Do do
|
||||
Params
|
||||
Identifier x
|
||||
colon :
|
||||
FunctionCallOrIdentifier
|
||||
Identifier x
|
||||
keyword end
|
||||
`)
|
||||
})
|
||||
|
||||
test('call with function in named arg', () => {
|
||||
expect(`tail callback=do x: x end`).toMatchTree(`
|
||||
FunctionCall
|
||||
Identifier tail
|
||||
NamedArg
|
||||
NamedArgPrefix callback=
|
||||
FunctionDef
|
||||
Do do
|
||||
Params
|
||||
Identifier x
|
||||
colon :
|
||||
FunctionCallOrIdentifier
|
||||
Identifier x
|
||||
keyword end
|
||||
`)
|
||||
})
|
||||
|
||||
|
||||
test('command with arg that is also a command', () => {
|
||||
expect('tail tail').toMatchTree(`
|
||||
FunctionCall
|
||||
|
|
|
|||
|
|
@ -336,6 +336,22 @@ describe('dict literals', () => {
|
|||
`)
|
||||
})
|
||||
|
||||
test('work with functions', () => {
|
||||
expect(`[trap=do x: x end]`).toMatchTree(`
|
||||
Dict
|
||||
NamedArg
|
||||
NamedArgPrefix trap=
|
||||
FunctionDef
|
||||
Do do
|
||||
Params
|
||||
Identifier x
|
||||
colon :
|
||||
FunctionCallOrIdentifier
|
||||
Identifier x
|
||||
keyword end
|
||||
`)
|
||||
})
|
||||
|
||||
test('can be nested', () => {
|
||||
expect('[a=one b=[two [c=three]]]').toMatchTree(`
|
||||
Dict
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user