do allowed in arg/dict values
This commit is contained in:
parent
9e4471ad38
commit
566beb87ef
|
|
@ -241,6 +241,22 @@ export class Parser {
|
||||||
// parse specific nodes
|
// 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 ]
|
// [ 1 2 3 ]
|
||||||
array(): SyntaxNode {
|
array(): SyntaxNode {
|
||||||
const open = this.expect($T.OpenBracket)
|
const open = this.expect($T.OpenBracket)
|
||||||
|
|
@ -425,10 +441,7 @@ export class Parser {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.is($T.NamedArgPrefix))
|
values.push(this.is($T.NamedArgPrefix) ? this.namedArg() : this.arg())
|
||||||
values.push(this.namedArg())
|
|
||||||
else
|
|
||||||
values.push(this.value())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const close = this.expect($T.CloseBracket)
|
const close = this.expect($T.CloseBracket)
|
||||||
|
|
@ -549,17 +562,8 @@ export class Parser {
|
||||||
const ident = fn ?? this.identifier()
|
const ident = fn ?? this.identifier()
|
||||||
|
|
||||||
const args: SyntaxNode[] = []
|
const args: SyntaxNode[] = []
|
||||||
while (!this.isExprEnd() && !this.is($T.Operator, '|')) {
|
while (!this.isExprEnd() && !this.is($T.Operator, '|'))
|
||||||
if (this.is($T.NamedArgPrefix)) {
|
args.push(this.is($T.NamedArgPrefix) ? this.namedArg() : this.arg())
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const node = new SyntaxNode('FunctionCall', ident.from, (args.at(-1) || ident).to)
|
const node = new SyntaxNode('FunctionCall', ident.from, (args.at(-1) || ident).to)
|
||||||
node.push(ident, ...args)
|
node.push(ident, ...args)
|
||||||
|
|
@ -669,7 +673,7 @@ export class Parser {
|
||||||
// abc= true
|
// abc= true
|
||||||
namedArg(): SyntaxNode {
|
namedArg(): SyntaxNode {
|
||||||
const prefix = SyntaxNode.from(this.expect($T.NamedArgPrefix))
|
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)
|
const node = new SyntaxNode('NamedArg', prefix.from, val.to)
|
||||||
return node.push(prefix, val)
|
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', () => {
|
test('command with arg that is also a command', () => {
|
||||||
expect('tail tail').toMatchTree(`
|
expect('tail tail').toMatchTree(`
|
||||||
FunctionCall
|
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', () => {
|
test('can be nested', () => {
|
||||||
expect('[a=one b=[two [c=three]]]').toMatchTree(`
|
expect('[a=one b=[two [c=three]]]').toMatchTree(`
|
||||||
Dict
|
Dict
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user