Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # use trace;
- grammar NaturalG {
- token ws { :i \s* '(' \s* 'note' \s* 'that' \s* [<nonordinal> \s*]* ')' \s* || \s* }
- # verb = operator (infix), noun = fn (prefix)
- rule TOP { [ <stmt> '.' ]* }
- proto rule fn { * }
- rule fn:sym<prep> { :i 'let' <ident> <ident>+ <ident> 'be' <expr> '.' }
- rule fn:sym<verb> { :i 'to' <ident> <id_list> <body> }
- rule fn:sym<noun> { :i 'let' 'the' <ordinal_word> [ <[a..z-]>+ ]* 'be' <expr> '.' } # this would mutate the parser
- proto rule body { * }
- rule body:sym<single> { ','? <stmt> '.' }
- rule body:sym<multiple> { :i ':' 'firstly' ','? <stmt> '.' (('then' ','?)? <stmt>)* 'finally' ','? <stmt> '.'}
- proto rule stmt { * }
- # rule stmt:sym<if> { :i 'if' <expr> 'then'? <body> [ 'else' <body> ]? }
- rule stmt:sym<action> { :i <verb> <expr> }
- rule stmt:sym<let> { :i 'let' <var> 'be' <expr> }
- # rule stmt:sym<assign> { :i 'assign' <expr> 'to' <var> }
- rule stmt:sym<fn> { :i <fn> }
- proto rule var { * }
- rule var:sym<implicit> { :i <ident> }
- rule var:sym<explicit> { :i 'the' <ident> <ident> }
- rule expr { <flow_expr> }
- proto rule flow_expr { * }
- rule flow_expr:sym<if> { :i <prep_expr> 'if' <prep_expr> ','? 'else' <prep_expr> }
- rule flow_expr:sym<prep> { <prep_expr> }
- rule prep_expr { <atomic> [ <prep> <atomic> ]* }
- proto rule verb { * }
- rule verb:sym<output> { :i <sym> }
- proto rule prep { * }
- rule prep:sym<plus> { :i <sym> }
- rule prep:sym<minus> { :i <sym> }
- rule prep:sym<times> { :i <sym> }
- rule prep:sym<divide> { :i 'divided' 'by' }
- rule prep:sym<modulo> { :i <sym> }
- rule prep:sym<power> { :i 'to' 'the' 'power' 'of' }
- rule prep:sym<equals> { :i ['does' || 'is'] 'equal' 'to'? }
- rule prep:sym<not_equals> { :i ['does' || 'is'] 'not' 'equal' 'to'? }
- rule prep:sym<less_eq> { :i 'is' ['lesser' || 'less'] 'than' 'or' 'equal' 'to' }
- rule prep:sym<more_eq> { :i 'is' ['greater' || 'more'] 'than' 'or' 'equal' 'to' }
- rule prep:sym<less_than> { :i 'is' ['lesser' || 'less'] 'than' }
- rule prep:sym<more_than> { :i 'is' ['greater' || 'more'] 'than' }
- rule prep:sym<concat> { :i ['concatenated' || 'joined'] 'with' }
- proto rule atomic { * }
- rule atomic:sym<list> { <list> }
- rule atomic:sym<nonlist> { <nonlist> }
- proto rule nonlist { * }
- rule nonlist:sym<ordinal> { :i 'the' <ordinal_word> <sequence> }
- rule nonlist:sym<nonordinal> { <nonordinal> }
- proto rule sequence { * }
- rule sequence:sym<fib> { :i 'fibonacci' 'number' }
- rule ordinal_word { :i <nonordinal> '-' [ 'th' || 'rd' || 'nd' || 'st' ] }
- proto rule nonordinal { * }
- rule nonordinal:sym<paren> { '(' <expr> ')' }
- # TODO: '[' <foo> ']' - arrays?
- rule nonordinal:sym<typed> { :i 'the' <ident> <expr> }
- token nonordinal:sym<decimal> { \d+ '.' \d+ }
- token nonordinal:sym<integer> { \d+ }
- token nonordinal:sym<string> { '"' [ '\\' <[ \\ " ]> ]* '"' }
- token nonordinal:sym<ident> { <ident> }
- rule list { :i <nonlist> (',' <nonlist>)* ','? 'and' <nonlist> }
- rule id_list { :i <ident> (',' <ident>)* ','? 'and' <ident> || :i <ident> }
- token ident { :i <[a..z-]>+ }
- }
- q:to<ENDCOMMENT>
- use MONKEY-TYPING;
- augment grammar NaturalG {
- rule verb:sym<xd> { 'xd' }
- }
- ENDCOMMENT
- ;
- class Natural {
- method TOP($/) {
- say 'parse', $/;
- my @lambdas = $<stmt>.map: *.made;
- make ->|args {
- my $result;
- for @lambdas {
- $result = $_(|args);
- };
- $result
- }
- }
- method body:sym<single>($/) { make $<stmt>.made }
- method body:sym<multiple>($/) { make $<stmt>.made }
- method stmt:sym<action>($/) {
- my &verb = $<verb>.made;
- my &arg = $<expr>.made;
- make ->|args {
- &verb(|args)(&arg(|args))
- # right now it's just a single object - argument lists are a single heterogeneous list
- }
- }
- method expr($/) { make $<flow_expr>.made }
- method flow_expr:sym<prep>($/) { make $<prep_expr>.made }
- method prep_expr($/) {
- my $i = 0;
- my &result = $<atomic>[0].made;
- while ($i < $<prep>.elems) {
- &result = (->&prep, &result, &atomic { ->|args {
- &prep(|args)(&result(|args), &atomic(|args))
- }})($<prep>[$i].made, &result, $<atomic>[$i + 1].made);
- $i++;
- }
- make &result
- }
- method verb:sym<output>($/) { make ->{ *.say } }
- method prep:sym<plus>($/) { make ->{ * + * } }
- method prep:sym<minus>($/) { make ->{ * - * } }
- method prep:sym<times>($/) { make ->{ * * * } }
- method prep:sym<divide>($/) { make ->{ * / * } }
- method prep:sym<modulo>($/) { make ->{ * % * } }
- method prep:sym<power>($/) { make ->{ * ** * } }
- method prep:sym<equals>($/) { make ->{ * == * } }
- method prep:sym<not_equals>($/) { make ->{ * != * } }
- method prep:sym<less_eq>($/) { make ->{ * <= * } }
- method prep:sym<more_eq>($/) { make ->{ * >= * } }
- method prep:sym<less_than>($/) { make ->{ * < * } }
- method prep:sym<more_than>($/) { make ->{ * > * } }
- method prep:sym<concat>($/) { make ->{ * ~ * } }
- method atomic:sym<list>($/) { make $<list>.made }
- method atomic:sym<nonlist>($/) { make $<nonlist>.made }
- method nonlist:sym<nonordinal>($/) { make $<nonordinal>.made }
- method nonordinal:sym<typed>($/) { make $<expr>.made } # TODO - enforce typing
- method nonordinal:sym<decimal>($/) { my $result = +$/; make { $result } }
- method nonordinal:sym<string>($/) { say $/, $/.substr(1, *-1); my $result = $/.substr(1, *-1).subst(/'\\' (.)/, { " before $0 after " }); say 'result "', $result, '"'; make { $result } }
- method nonordinal:sym<integer>($/) { my $result = +$/; make { $result } }
- method nonordinal:sym<paren>($/) { make $<expr>.made }
- method list($/) {
- my @lambdas = ($<nonlist>[0], |$/[0].map(*.<nonlist>), $<nonlist>[1]).map: *.made;
- make ->|args {
- @lambdas.map: {$_(|args)}
- }
- }
- }
- class Scope {
- }
- my $scope = Scope.new();
- NaturalG.parse(
- q:to<FIB>
- output 1, 2, 3 (note that this is funny), "\"\"" and (4 plus 96.5).
- FIB
- , actions => Natural).made()();
- # 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