Advertisement
Guest User

Untitled

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