我目前正在尝试描述一些基本的Ruby语法,但现在我被函数定义所困。事实上,我不知道如何处理“n”参数。下面是我用来处理包含0到2个参数的函数的代码:
rule function_definition
'def' space? identifier space? '(' space? expression? space? ','? expression? space? ')'
block
space? 'end' <FunctionDefinition>
end
我该如何处理'n‘参数?有没有什么递归的方法可以做到这一点?
编辑:
我想强调这样一个事实,即我需要将参数放在结果树中。像这样:
Argument offset=42, "arg1"
Argument offset=43, "arg2"
Argument offset=44, "arg3"
所以我需要做一个cstom SyntaxNode子类声明,就像我对function_definition规则所做的那样。
发布于 2011-11-08 19:17:33
你想要像这样的东西(未测试):
'def' space? identifier space? '(' space? ( expression ( space? ',' expression )* )? space? ')'
(注意,如果这是一个拼音风格的def
,那么在没有参数的情况下,括号也是可选的)
编辑以演示从解析树中提取参数--这里我列出了每个参数的text_value
(FunctionArg
)语法节点,但您当然可以执行任何操作:
foo.rb:
# Prepend current directory to load path
$:.push('.')
# Load treetop grammar directly without compilation
require 'polyglot'
require 'treetop'
require 'def'
# Classes for bespoke nodes
class FunctionDefinition < Treetop::Runtime::SyntaxNode ; end
class FunctionArg < Treetop::Runtime::SyntaxNode ; end
# Some tests
[
'def foo() block end',
'def foo(arg1) block end',
'def foo(arg1, arg2) block end',
'def foo(arg1, arg2, arg3) block end',
].each do |test|
parser = DefParser.new
tree = parser.parse( test )
raise RuntimeError, "Parsing failed on line:\n#{test}" unless tree
puts test
puts "identifier=#{tree.function_identifier}"
puts "args=#{tree.function_args.inspect}"
puts
end
def.tt:
grammar Def
# Top level rule: a function
rule function_definition
'def' space identifier space? '(' space? arg0 more_args space? ')' space block space 'end' <FunctionDefinition>
{
def function_identifier
identifier.text_value
end
def function_args
arg0.is_a?( FunctionArg ) ? [ arg0.text_value ] + more_args.args : []
end
}
end
# First function argument
rule arg0
argument?
end
# Second and further function arguments
rule more_args
( space? ',' space? argument )*
{
def args
elements.map { |e| e.elements.last.text_value }
end
}
end
# Function identifier
rule identifier
[a-zA-Z_] [a-zA-Z0-9_]*
end
# TODO Dummy rule for function block
rule block
'block'
end
# Function argument
rule argument
[a-zA-Z_] [a-zA-Z0-9_]* <FunctionArg>
end
# Horizontal whitespace (htab or space character).
rule space
[ \t]
end
end
输出:
def foo() block end
identifier=foo
args=[]
def foo(arg1) block end
identifier=foo
args=["arg1"]
def foo(arg1, arg2) block end
identifier=foo
args=["arg1", "arg2"]
def foo(arg1, arg2, arg3) block end
identifier=foo
args=["arg1", "arg2", "arg3"]
发布于 2015-08-17 18:28:41
更好的方法可能是使用递归。
rule function_definition
'def' space identifier space? '(' space? argList? space? ')' block 'end'
end
rule argList
identifier space? ',' space? argList
/ identifier
end
https://stackoverflow.com/questions/8048163
复制相似问题