5 This is the grammar for cardinal written as a sequence of Perl 6 rules.
7 Currently taken (partly) from:
8 http://www.math.hokudai.ac.jp/~gotoken/ruby/man/yacc.html
10 and parse.y from the ruby source
12 But adapted here and there; it's not entirely correct, it seems.
16 grammar cardinal::Grammar is PCT::Grammar;
20 [ $ || <panic: Syntax error> ]
31 <.term>?[ <stmt> [<.term>+ | <.before <end_block>> | $] ]* {*}
34 token term { \n | ';' }
35 token end_block { <.ws> [ 'end' | '}' ] }
38 | <alias> {*} #= alias
39 | <classdef> {*} #= classdef
40 | <functiondef> {*} #= functiondef
41 | <if_stmt> {*} #= if_stmt
42 | <while_stmt> {*} #= while_stmt
43 | <for_stmt> {*} #= for_stmt
44 | <unless_stmt> {*} #= unless_stmt
45 | <module> {*} #= module
46 | <begin_end> {*} #= begin_end
47 | <indexed_assignment> {*} #= indexed_assignment
48 | <assignment> {*} #= assignment
49 | <return_stmt> {*} #= return_stmt
51 | <begin> {*} #= begin
56 'return' <.ws> <call_args> {*}
60 'alias' <fname> <fname>
65 <basic_stmt> <.ws> <stmt_mod>*
70 $<sym>=[if|while|unless|until] <.ws> <expr>
75 $<not>=['not']? <arg> [$<op>=['and'|'or'] <expr>]?
80 'BEGIN' '{' <comp_stmt> '}'
85 'END' '{' <comp_stmt> '}'
89 token indexed_assignment {
90 <basic_primary> '[' <key=arg> ']' <.ws> '=' <.ws> <rhs=arg>
95 <mlhs=lhs> '=' <mrhs=arg> #XXX need to figure out multiple assignment
101 | '(' <mlhs> ')' {*} #= mlhs
105 | <basic_primary> {*} #= basic_primary
113 token member_variable {
114 <primary> '.' <identifier>
120 <operation> <call_args>? <do_block>?
125 | 'do' <do_args> <.term>? <comp_stmt> 'end' {*}
126 | '{' <do_args> <.term>? <comp_stmt> '}' {*}
135 <.identifier> ('!'|'?')?
141 | '(' <.ws> <args> <.ws> ')' {*}
145 '|' [ <identifier> [',' <identifier>]*]?'|' {*}
149 | <varname> {*} #= varname
156 [ <global> {*} #= global
157 | <instance_variable> {*} #= instance_variable
158 | <local_variable> {*} #= local_variable
159 | <constant_variable> {*} #= constant_variable
172 rule 'arg' is optable { ... }
174 proto 'infix:=' is precedence('1') is pasttype('copy') is lvalue(1) { ... }
178 token basic_primary {
179 | <literal> {*} #= literal
180 | <variable> {*} #= variable
181 | <array> {*} #= array
182 | <ahash> {*} #= ahash
183 | <pcomp_stmt> {*} #= pcomp_stmt
184 | <scope_identifier> {*} #= scope_identifier
188 <basic_primary> <post_primary_expr>*
192 token post_primary_expr {
193 | <indexed> {*} #= indexed
194 | <call_args> {*} #= call_args
195 | <methodcall> {*} #= methodcall
196 | <scope_identifier> {*} #= scope_identifier
197 | '[' <args>? ']' {*} #= args
200 token scope_identifier {
214 ['elsif' <expr> <.then>
221 token then { ':' | 'then' | <term> ['then']? }
224 $<sym>=['while'|'until'] <expr> <.do>
231 'for' <variable> 'in' <expr> <.do>
237 token do { ':' | 'do' | <term> ['do']? }
240 'unless' <expr> <.then> <comp_stmt>
247 'else' <.ws> <comp_stmt>
252 'ensure' <.ws> <comp_stmt>
258 ['rescue' <args> <.then> <comp_stmt>]+
263 'module' <module_identifier>
270 'class' <module_identifier> {*} #= open
276 'def' <fname> <argdecl>
291 [ <identifier> [',' <identifier>]* [',' <slurpy_param>]? [',' <block_param>]?
292 | <slurpy_param> [',' <block_param>]?
312 ['rescue' <args>? <.do> <comp_stmt>]+
313 ['else' <comp_stmt>]?
314 ['ensure' <comp_stmt>]?
324 '[' [ <args> [',']? ]? ']'
329 '{' [ [ <args> | <assocs> ] [',']? ]? '}'
334 <assoc> [',' <assoc>]*
344 <!reserved_word> <ident> {*}
347 token module_identifier {
348 <.before <[A..Z]>> <ident>
357 token instance_variable {
362 token class_variable {
367 token local_variable {
368 <before <[a..z_]>> <ident>
372 token constant_variable {
373 <before <[A..Z]>> <ident>
378 | <float> {*} #= float
379 | <integer> {*} #= integer
380 | <string> {*} #= string
394 [ \' <string_literal: "'"> \' | \" <string_literal: '"'> \" ]
398 token reserved_word {
399 [alias|and|BEGIN|begin|break|case
400 |class|def|defined|do|else|elsif
401 |END|end|ensure|false|for|if
402 |in|module|next|nil|not|or
403 |redo|rescue|retry|return|self|super
404 |then|true|undef|unless|until|when
405 |while|yield|__FILE__|__LINE__]>>
409 | '\\' \n ## a backslash at end of line
410 | <after [','|'='|'+']> \n ## a newline after a comma or operator is ignored
415 proto 'infix:=' is precedence('1') is pasttype('copy') is lvalue(1) { ... }
417 proto 'prefix:defined?' is looser('infix:=') { ... }
419 proto 'infix:+=' is equiv('infix:=')
420 is pirop('add') { ... }
422 proto 'infix:-=' is equiv('infix:=')
423 is pirop('sub') { ... }
425 proto 'infix:/=' is equiv('infix:=')
426 is pirop('div') { ... }
428 proto 'infix:*=' is equiv('infix:=')
429 is pirop('mul') { ... }
431 proto 'infix:%=' is equiv('infix:=')
432 is pirop('mul') { ... }
434 proto 'infix:|=' is equiv('infix:=') { ... }
436 proto 'infix:&=' is equiv('infix:=') { ... }
438 proto 'infix:~=' is equiv('infix:=') { ... }
440 proto infix:«>>=» is equiv('infix:=')
441 is pirop('rsh') { ... }
443 proto infix:«<<=» is equiv('infix:=')
444 is pirop('lsh') { ... }
446 proto 'infix:&&=' is equiv('infix:=')
447 is pirop('and') { ... }
449 proto 'infix:**=' is equiv('infix:=')
450 is pirop('pow') { ... }
452 proto 'ternary:? :' is tighter('infix:=')
453 is pirop('if') { ... }
455 proto 'infix:..' is tighter('ternary:? :')
456 is pirop('n_add') { ... }
458 proto 'infix:...' is equiv('infix:...') { ... }
460 proto 'infix:||' is tighter('infix:..')
461 is past('unless') { ... }
463 proto 'infix:&&' is tighter('infix:||')
464 is past('if') { ... }
467 proto 'infix:==' is tighter('infix:&&') { ... }
468 proto 'infix:!=' is equiv('infix:==') { ... }
469 proto 'infix:=~' is equiv('infix:==') { ... }
470 proto 'infix:!~' is equiv('infix:==') { ... }
471 proto 'infix:===' is equiv('infix:==') { ... }
472 proto infix:«<=>» is equiv('infix:==') { ... }
475 proto 'infix:«<=»' is tighter('infix:===') { ... }
476 proto infix:«=>» is tighter('infix:===') { ... }
477 proto infix:«>» is tighter('infix:===') { ... }
478 proto infix:«<» is tighter('infix:===') { ... }
480 proto 'infix:|' is tighter('infix:«<=»') { ... }
481 proto 'infix:^' is equiv('infix:|') { ... }
483 proto 'infix:&' is tighter('infix:|') { ... }
485 proto infix:«<<» is tighter('infix:&') { ... }
486 proto infix:«>>» is equiv(infix:«<<») { ... }
488 proto 'infix:+' is tighter(infix:«<<»)
489 is pirop('n_add') { ... }
491 proto 'infix:-' is equiv('infix:+')
492 is pirop('n_sub') { ... }
494 proto 'infix:*' is tighter('infix:+')
495 is pirop('n_mul') { ... }
497 proto 'infix:/' is equiv('infix:*')
498 is pirop('n_div') { ... }
500 proto 'infix:%' is equiv('infix:*')
501 is pirop('n_mod') { ... }
503 #proto 'prefix:+' is tighter('infix:*') { ... }
504 #proto 'prefix:-' is equiv('prefix:+') { ... }
505 #proto 'prefix:!' is equiv('prefix:+') { ... }
506 #proto 'prefix:~' is equiv('prefix:+') { ... }
508 proto 'term:' is tighter('infix:*')
509 is parsed(&primary) { ... }