Advertisement
Guest User

Untitled

a guest
May 31st, 2019
180
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 6 5.66 KB | None | 0 0
  1. # use trace;
  2.  
  3. grammar NaturalG {
  4.     # verb = operator (infix), noun = fn (prefix)
  5.     rule TOP { [ <stmt> '.' ]* }
  6.     proto rule fn { * }
  7.         rule fn:sym<prep> { :i 'let' <ident> <ident>+ <ident> 'be' <expr> '.' }
  8.         rule fn:sym<verb> { :i 'to' <ident> <id_list> <body> }
  9.         rule fn:sym<noun> { :i 'let' 'the' <ordinal_word> [ <[a..z-]>+ ]* 'be' <expr> '.' } # this would mutate the parser
  10.     proto rule body { * }
  11.         rule body:sym<single> { ','? <stmt> '.' }
  12.         rule body:sym<multiple> { :i ':' 'firstly' ','? <stmt> '.' (('then' ','?)? <stmt>)* 'finally' ','? <stmt> '.'}
  13.     proto rule stmt { * }
  14.         # rule stmt:sym<if> { :i 'if' <expr> 'then'? <body> [ 'else' <body> ]? }
  15.         rule stmt:sym<action> { :i <verb> <expr> }
  16.         rule stmt:sym<assn> { :i 'let' <var> 'be' <expr> }
  17.         rule stmt:sym<fn> { :i <fn> }
  18.     proto rule var { * }
  19.         rule var:sym<implicit> { :i <ident> }
  20.         rule var:sym<explicit> { :i 'the' <ident> <ident> }
  21.     rule expr { <flow_expr> }
  22.     proto rule flow_expr { * }
  23.         rule flow_expr:sym<if> { :i <prep_expr> 'if' <prep_expr> ','? 'else' <prep_expr> }
  24.         rule flow_expr:sym<prep> { <prep_expr> }
  25.     rule prep_expr { <atomic> [ <prep> <atomic> ]* }
  26.     proto rule verb { * }
  27.         rule verb:sym<output> { :i <sym> }
  28.     proto rule prep { * }
  29.         rule prep:sym<plus> { :i <sym> }
  30.         rule prep:sym<minus> { :i <sym> }
  31.         rule prep:sym<times> { :i <sym> }
  32.         rule prep:sym<divide> { :i 'divided' 'by' }
  33.         rule prep:sym<modulo> { :i <sym> }
  34.         rule prep:sym<power> { :i 'to' 'the' 'power' 'of' }
  35.         rule prep:sym<equals> { :i ['does' || 'is'] 'equal' 'to'? }
  36.         rule prep:sym<not_equals> { :i ['does' || 'is'] 'not' 'equal' 'to'? }
  37.         rule prep:sym<less_eq> { :i 'is' ['less' || 'lesser'] 'than' 'or' 'equal' 'to' }
  38.         rule prep:sym<more_eq> { :i 'is' ['more' || 'greater'] 'than' 'or' 'equal' 'to' }
  39.         rule prep:sym<less_than> { :i 'is' ['less' || 'lesser'] 'than' }
  40.         rule prep:sym<more_than> { :i 'is' ['more' || 'greater'] 'than' }
  41.         rule prep:sym<concat> { :i ['concatenated' || 'joined'] 'with' }
  42.     proto rule atomic { * }
  43.         rule atomic:sym<list> { <list> }
  44.         rule atomic:sym<nonlist> { <nonlist> }
  45.     proto rule nonlist { * }
  46.         rule nonlist:sym<ordinal> { :i 'the' <ordinal_word> <sequence> }
  47.         rule nonlist:sym<nonordinal> { <nonordinal> }
  48.     proto rule sequence { * }
  49.         rule sequence:sym<fib> { :i 'fibonacci' 'number' }
  50.     rule ordinal_word { :i <nonordinal> '-' ['th' || 'rd' || 'nd' || 'st' ] }
  51.     proto rule nonordinal { * }
  52.         rule nonordinal:sym<paren> { '(' <expr> ')' }
  53.         rule nonordinal:sym<typed> { :i 'the' <ident> <expr> }
  54.         token nonordinal:sym<decimal> { \d+ '.' \d+ }
  55.         token nonordinal:sym<integer> { \d+ }
  56.         token nonordinal:sym<string> { '"' ['\\' <[ \\ " ]> || <-[ \\ " ]>]* '"' }
  57.         token nonordinal:sym<ident> { <ident> }
  58.     rule list { :i <nonlist> (',' <nonlist>)* ','? 'and' <nonlist> }
  59.     rule id_list { :i <ident> (',' <ident>)* ','? 'and' <ident> | :i <ident> }
  60.     token ident { :i <[a..z-]>+ }
  61. }
  62. q:to<ENDCOMMENT>
  63. use MONKEY-TYPING;
  64. augment grammar NaturalG {
  65.     rule verb:sym<xd> { 'xd' }
  66. }
  67. ENDCOMMENT
  68. ;
  69. class Natural {
  70.     method TOP($/) {
  71.         my @lambdas = $<stmt>.map: *.made;
  72.         make ->|args {
  73.             my $result;
  74.             for @lambdas {
  75.                 $result = $_(|args);
  76.             };
  77.             $result
  78.         }
  79.     }
  80.     method body:sym<single>($/) { make $<stmt>.made }
  81.     method body:sym<multiple>($/) { make $<stmt>.made }
  82.     method stmt:sym<action>($/) {
  83.         my &verb = $<verb>.made;
  84.         my &arg = $<expr>.made;
  85.         make ->|args {
  86.             &verb(|args)(&arg(|args))
  87.             # right now it's just a single object - argument lists are a single heterogeneous list
  88.         }
  89.     }
  90.     method expr($/) { make $<flow_expr>.made }
  91.     method flow_expr:sym<prep>($/) { make $<prep_expr>.made }
  92.     method prep_expr($/) {
  93.         my $i = 0;
  94.         my &result = $<atomic>[0].made;
  95.         while ($i < $<prep>.elems) {
  96.             &result = (->&prep, &result, &atomic { ->|args {
  97.                 &prep(|args)(&result(|args), &atomic(|args))
  98.             }})($<prep>[$i].made, &result, $<atomic>[$i + 1].made);
  99.             $i++;
  100.         }
  101.         make &result
  102.     }
  103.     method verb:sym<output>($/) { make ->{ *.say } }
  104.  
  105.     method prep:sym<plus>($/) { make ->{ * + * } }
  106.     method prep:sym<minus>($/) { make ->{ * - * } }
  107.     method prep:sym<times>($/) { make ->{ * * * } }
  108.     method prep:sym<divide>($/) { make ->{ * / * } }
  109.     method prep:sym<modulo>($/) { make ->{ * % * } }
  110.     method prep:sym<power>($/) { make ->{ * ** * } }
  111.     method prep:sym<equals>($/) { make ->{ * == * } }
  112.     method prep:sym<not_equals>($/) { make ->{ * != * } }
  113.     method prep:sym<less_eq>($/) { make ->{ * <= * } }
  114.     method prep:sym<more_eq>($/) { make ->{ * >= * } }
  115.     method prep:sym<less_than>($/) { make ->{ * < * } }
  116.     method prep:sym<more_than>($/) { make ->{ * > * } }
  117.     method prep:sym<concat>($/) { make ->{ * ~ * } }
  118.  
  119.     method atomic:sym<list>($/) { make $<list>.made }
  120.     method atomic:sym<nonlist>($/) { make $<nonlist>.made }
  121.     method nonlist:sym<nonordinal>($/) { make $<nonordinal>.made }
  122.  
  123.     method nonordinal:sym<typed>($/) { make $<expr>.made } # TODO - enforce typing
  124.     method nonordinal:sym<decimal>($/) { my $result = +$/; make { $result } }
  125.     method nonordinal:sym<string>($/) { say $/; my $result = $/.substr(1, *-1).subst(/\\(.)/, { "$1" }); say $result; make { $result } }
  126.     method nonordinal:sym<integer>($/) { my $result = +$/; make { $result } }
  127.     method nonordinal:sym<paren>($/) { make $<expr>.made }
  128.  
  129.     method list($/) {
  130.         my @lambdas = ($<nonlist>[0], |$/[0].map(*.<nonlist>), $<nonlist>[1]).map: *.made;
  131.         make ->|args {
  132.             @lambdas.map: {$_(|args)}
  133.         }
  134.     }
  135. }
  136. class Scope {
  137. }
  138. my $scope = Scope.new();
  139. NaturalG.parse(
  140. q:to<FIB>
  141. output 1, 2, 3, (3 concatenated with "a" concatenated with "b") and (4 plus 96.5).
  142. FIB
  143. , actions => Natural).made()();
  144. # to fib n and o: firstly, let a be 1 plus 1, 2, 3, and 4. finally, let b be 2 plus 2 if a is greater than 1 else 0.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement