首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >树顶解析器:函数定义语法-n参数

树顶解析器:函数定义语法-n参数
EN

Stack Overflow用户
提问于 2011-11-08 17:17:34
回答 2查看 529关注 0票数 3

我目前正在尝试描述一些基本的Ruby语法,但现在我被函数定义所困。事实上,我不知道如何处理“n”参数。下面是我用来处理包含0到2个参数的函数的代码:

代码语言:javascript
运行
复制
  rule function_definition
    'def' space? identifier space? '(' space? expression? space? ','? expression? space? ')'
      block
    space? 'end' <FunctionDefinition>
  end  

我该如何处理'n‘参数?有没有什么递归的方法可以做到这一点?

编辑:

我想强调这样一个事实,即我需要将参数放在结果树中。像这样:

代码语言:javascript
运行
复制
 Argument offset=42, "arg1"
 Argument offset=43, "arg2"
 Argument offset=44, "arg3"

所以我需要做一个cstom SyntaxNode子类声明,就像我对function_definition规则所做的那样。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-11-08 19:17:33

你想要像这样的东西(未测试):

代码语言:javascript
运行
复制
'def' space? identifier space? '(' space? ( expression ( space? ',' expression )* )? space?  ')'

(注意,如果这是一个拼音风格的def,那么在没有参数的情况下,括号也是可选的)

编辑以演示从解析树中提取参数--这里我列出了每个参数的text_value (FunctionArg)语法节点,但您当然可以执行任何操作:

foo.rb:

代码语言:javascript
运行
复制
# 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:

代码语言:javascript
运行
复制
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

输出:

代码语言:javascript
运行
复制
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"]
票数 1
EN

Stack Overflow用户

发布于 2015-08-17 18:28:41

更好的方法可能是使用递归。

代码语言:javascript
运行
复制
rule function_definition
  'def' space identifier space? '(' space? argList? space? ')' block 'end'
end

rule argList
   identifier space? ',' space? argList
   / identifier
end
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8048163

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档