在Raku中,如何从字符串中动态创建代码对象?

发布于 2025-02-08 12:01:49 字数 2649 浏览 1 评论 0原文


在Raku版本v2022.06中,我试图动态创建语法G具有两种作品……

  1. S→
  2. λS→ASB

我的草稿程序是…

sub MAIN ( )
  {
  my @variableRightHandSidesMap is Array[Pair] ;
  @variableRightHandSidesMap.push: Pair.new("S", "") ;
  @variableRightHandSidesMap.push: Pair.new("S", "'a' <S> 'b'") ;

  constant Parser := Metamodel::GrammarHOW.new_type( name => 'Parser' ) ;

  my $myTopCode = my token TOP { <S> } ;
  my $mySCode = my token S { '' | 'a' <S> 'b' } ;

  Parser.^add_method( 'TOP', $myTopCode ) ;
  Parser.^add_method( 'S', $mySCode ) ;

  Parser.^compose ;
  say Parser.HOW.^name ;
  say Parser.^methods( :local ) ;
  say ?(Parser.parse: 'aabb') ;
  say ?(Parser.parse: 'aaaaabbbbb') ;
  say ?(Parser.parse: 'aabbb') ;
  say ?(Parser.parse: 'abab') ;
  } # end sub MAIN

程序输出是……

Perl6::Metamodel::GrammarHOW
(token TOP { <S> } token S { '' | 'a' <S> 'b' })
True
True
False
False

上面显示的草稿程序具有$ mytopcode$ myScode硬编码。

但是,一个人如何(通过编程)动态地创建代码对象$ mytopcode$ myScode@中的一对字符串。 variablerighthandsidesmap


更新…

下面的答案使我获得了以下草稿,该草稿产生了希望的产出(如上所示)……

use MONKEY-SEE-NO-EVAL ;

sub MAIN ( )
  {
  my @variableRightHandSidesMap is Array[Pair] ;
  @variableRightHandSidesMap.push: Pair.new("S", "") ;
  @variableRightHandSidesMap.push: Pair.new("S", "'a' <S> 'b'") ;

  constant Parser := Metamodel::GrammarHOW.new_type( name => 'Parser' ) ;

  my $startVariable = @variableRightHandSidesMap[0].key ; # 'S'
  my $myTopCode = EVAL ( 'my token TOP { <' ~ $startVariable ~ '> }' ) ;
  Parser.^add_method( 'TOP', $myTopCode ) ;

  my Str $sCumulativeRightHandSide = '' ;
  loop ( my $i = 0 ; $i < @variableRightHandSidesMap.elems ; $i++ )
    {
    if ( $i > 0 )
      {
      $sCumulativeRightHandSide ~= ( ' | ' ) ;
      }
    if ( @variableRightHandSidesMap[$i].value.chars <= 0 )
      {
      $sCumulativeRightHandSide ~= ( '\'\'' ) ;
      }
    else
      {
      $sCumulativeRightHandSide ~= ( @variableRightHandSidesMap[$i].value ) ;
      } # end else
    } # end loop

  my $mySCode = EVAL ( 'my token ' ~ 'S' ~ ' { ' ~ $sCumulativeRightHandSide ~ ' }' ) ;
  Parser.^add_method( 'S', $mySCode ) ;

  Parser.^compose ;
  say Parser.HOW.^name ;
  say Parser.^methods( :local ) ;
  say ?(Parser.parse: 'aabb') ;
  say ?(Parser.parse: 'aaaaabbbbb') ;
  say ?(Parser.parse: 'aabbb') ;
  say ?(Parser.parse: 'abab') ;
  } # end sub MAIN

任何建议(例如,提出上述草稿更简洁的建议)将不胜感激。



In Raku version v2022.06, I am trying to dynamically create grammar G having two productions …

  1. S → λ
  2. S → aSb

My draft program is …

sub MAIN ( )
  {
  my @variableRightHandSidesMap is Array[Pair] ;
  @variableRightHandSidesMap.push: Pair.new("S", "") ;
  @variableRightHandSidesMap.push: Pair.new("S", "'a' <S> 'b'") ;

  constant Parser := Metamodel::GrammarHOW.new_type( name => 'Parser' ) ;

  my $myTopCode = my token TOP { <S> } ;
  my $mySCode = my token S { '' | 'a' <S> 'b' } ;

  Parser.^add_method( 'TOP', $myTopCode ) ;
  Parser.^add_method( 'S', $mySCode ) ;

  Parser.^compose ;
  say Parser.HOW.^name ;
  say Parser.^methods( :local ) ;
  say ?(Parser.parse: 'aabb') ;
  say ?(Parser.parse: 'aaaaabbbbb') ;
  say ?(Parser.parse: 'aabbb') ;
  say ?(Parser.parse: 'abab') ;
  } # end sub MAIN

Program output is …

Perl6::Metamodel::GrammarHOW
(token TOP { <S> } token S { '' | 'a' <S> 'b' })
True
True
False
False

The draft program shown above has $myTopCode and $mySCode hardcoded.

However, how does one dynamically (programmatically) create the Code objects $myTopCode and $mySCode from the pairs of strings in the @variableRightHandSidesMap ?


Update …

The answers below led me to the following draft, which produces the hoped‑for output (as shown above) …

use MONKEY-SEE-NO-EVAL ;

sub MAIN ( )
  {
  my @variableRightHandSidesMap is Array[Pair] ;
  @variableRightHandSidesMap.push: Pair.new("S", "") ;
  @variableRightHandSidesMap.push: Pair.new("S", "'a' <S> 'b'") ;

  constant Parser := Metamodel::GrammarHOW.new_type( name => 'Parser' ) ;

  my $startVariable = @variableRightHandSidesMap[0].key ; # 'S'
  my $myTopCode = EVAL ( 'my token TOP { <' ~ $startVariable ~ '> }' ) ;
  Parser.^add_method( 'TOP', $myTopCode ) ;

  my Str $sCumulativeRightHandSide = '' ;
  loop ( my $i = 0 ; $i < @variableRightHandSidesMap.elems ; $i++ )
    {
    if ( $i > 0 )
      {
      $sCumulativeRightHandSide ~= ( ' | ' ) ;
      }
    if ( @variableRightHandSidesMap[$i].value.chars <= 0 )
      {
      $sCumulativeRightHandSide ~= ( '\'\'' ) ;
      }
    else
      {
      $sCumulativeRightHandSide ~= ( @variableRightHandSidesMap[$i].value ) ;
      } # end else
    } # end loop

  my $mySCode = EVAL ( 'my token ' ~ 'S' ~ ' { ' ~ $sCumulativeRightHandSide ~ ' }' ) ;
  Parser.^add_method( 'S', $mySCode ) ;

  Parser.^compose ;
  say Parser.HOW.^name ;
  say Parser.^methods( :local ) ;
  say ?(Parser.parse: 'aabb') ;
  say ?(Parser.parse: 'aaaaabbbbb') ;
  say ?(Parser.parse: 'aabbb') ;
  say ?(Parser.parse: 'abab') ;
  } # end sub MAIN

Any suggestions (such as those making the above draft more concise) would be appreciated.


如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦境 2025-02-15 12:01:49

函数可以用来解析,编译和评估Raku来源。如果要产生某种代码对象,请确保评估的表达式是一个代码对象,例如evar'anon Regex {x}'

The EVAL function can be used to parse, compile, and evaluate Raku source. If you want to produce some kind of code object, then make sure the evaluated expression is a code object, e.g. EVAL 'anon regex { x }'.

完美的未来在梦里 2025-02-15 12:01:49

在Rakuast分支降落之前,我会说使用eval

您可以在目前的Raku语法中使用Spelunk来找出目前的完成方式,但是不能保证在Rakuast分支降落之后仍然可以正常工作。

rakuast分支降落后,将是稳定的API。

Until the RakuAST branch lands, I'd say use EVAL.

You could spelunk in the current Raku grammar to find out how that it is currently done, but there would be no guarantee that that would still work after the RakuAST branch lands.

After the RakuAST branch lands, there would be a stable API to do this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文