Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
332 lines (237 sloc) 5.82 KB
# Copyright (C) 2006-2009, Parrot Foundation.
# $Id$
=head1 a Lua 5.1 grammar in PGE
=head2 Description
=head3 Grammar Rules
The grammar rules are according to the original Lua parser as defined lparser.c
in the lua distribution.
=cut
grammar Lua::Grammar;
token TOP {
^ <shebang>? <block> <eof>
}
rule block {
[ <statement> ';'? ]*
}
rule statement {
| <expression_stat>
| <if_stat>
| <while_stat>
| <do_block>
| <for_stat>
| <repeat_stat>
| <function_stat>
| <local_stat>
| <return_statement>
| <break_statement>
| <unexpected>
}
rule expression_stat {
<primary_expression> <assignment>?
}
rule assignment {
| ',' <primary_expression> <assignment>
| '=' <expression_list>
}
rule expression_list {
<expression> [ ',' <expression> ]*
}
rule if_stat {
'if' <expression> <.then> <block> <elseif_block>* <else_block>? <.end>
}
rule elseif_block {
'elseif' <expression> <.then> <block>
}
rule else_block {
'else' <block>
}
rule while_stat {
'while' <expression> <.do> <block> <.end>
}
rule do_block {
'do' <block> <.end>
}
rule for_stat {
'for' [ <fornum> | <forlist> ] <for_body>
}
rule fornum {
<Name> '=' <expression> <.comma> <expression> [ ',' <expression> ]?
}
rule forlist {
<name_list> <.in> <expression_list>
}
rule for_body {
<.do> <block> <.end>
}
rule repeat_stat {
'repeat' <block> <.until> <expression>
}
rule function_stat {
'function' <functionname> <function_body>
}
rule functionname {
<Name> [ '.' <Name> ]* [ ':' <Name> ]?
}
rule function_body {
'(' <parameter_list> <.closeparen> <block> <.end>
}
rule parameter_list {
| <name_list> [ ',' <vararg> ]?
| <vararg>?
}
rule name_list {
<Name> [ ',' <Name> ]*
}
rule local_stat {
'local' [ <local_function> | <local_declaration> ]
}
rule local_function {
'function' <Name> <function_body>
}
rule local_declaration {
<Name> [ ',' <Name> ]* [ '=' <expression_list> ]?
}
rule return_statement {
'return' <expression_list>?
}
token break_statement {
'break'
}
rule constructor {
'{' <tablefieldlist>? <.closebrace>
}
rule tablefieldlist {
<tablefield> [ <[,;]> <tablefield> ]* <[,;]>?
}
rule tablefield {
<record_field> | <expression>
}
rule record_field {
[ <Name> | <index> ] '=' <expression>
}
rule index {
'[' <expression> <.closebracket>
}
rule primary_expression {
<prefix_expression> <slice_expression>*
}
rule prefix_expression {
| <parenthesed_expression>
| <Name>
}
rule parenthesed_expression {
'(' <expression> <.closeparen>
}
rule slice_expression {
| '.' <Name>
| <index>
| ':' <Name> <function_args>
| <function_args>
}
rule function_args {
| '(' <expression_list>? <.closeparen>
| <constructor>
| <string>
}
rule simple_expression {
| <number>
| <string>
| <nil>
| <true>
| <false>
| <vararg>
| <constructor>
| 'function' <function_body>
| <primary_expression>
}
=head3 Helper Rules
Helper rules will match a specific token, otherwise a syntax error is generated.
These rules make the grammar more readable, so the calls to syntaxerror() are
not all over the grammar, but only in these rules.
=cut
rule do {
'do' | <syntaxerror: "'do' expected">
}
rule then {
'then' | <syntaxerror: "'then' expected">
}
rule end {
'end' | <syntaxerror: "'end' expected">
}
rule until {
'until' | <syntaxerror: "'until' expected">
}
rule comma {
',' | <syntaxerror: "',' expected">
}
rule in {
'in' | <syntaxerror: "'in' expected">
}
rule closebracket {
']' | <syntaxerror: "']' expected">
}
rule closebrace {
'}' | <syntaxerror: "'}' expected">
}
rule closeparen {
')' | <syntaxerror: "')' expected">
}
=head3 Tokens
Tokens not defined here (in PGE) are written in PIR in
F<languages/lua/src/lua51.pir>.
=cut
token string {
| \" <quoted_literal: "\""> \"
| \' <quoted_literal: "'"> \'
| <long_string>
}
token nil {
'nil'
}
token true {
'true'
}
token false {
'false'
}
token vararg {
'...'
}
token ws {
[ \s+
| '--' <long_comment>
| '--' \N*
]*
}
token eof {
$ | <syntaxerror: "'eof' expected">
}
token shebang {
'#' \N*
}
=head3 Expressions
Operator precedence is implemented using an optable.
=cut
rule 'expression' is optable { ... }
proto 'term:' is precedence('=')
is parsed(&simple_expression) { ... }
proto 'infix:^' is looser('term:') is pirop('pow')
is assoc('right') { ... }
proto 'prefix:not' is looser('infix:^') is pirop('not') { ... }
proto 'prefix:#' is equiv('prefix:not') is past('len') { ... }
proto 'prefix:-' is equiv('prefix:not') is pirop('neg') { ... }
proto 'infix:*' is looser('prefix:not') is pirop('mul') { ... }
proto 'infix:/' is equiv('infix:*') is pirop('div') { ... }
proto 'infix:%' is equiv('infix:*') is pirop('mod') { ... }
proto 'infix:+' is looser('infix:*') is pirop('add') { ... }
proto 'infix:-' is equiv('infix:+') is pirop('sub') { ... }
proto 'infix:..' is looser('infix:+') is pirop('concat')
is assoc('right') { ... }
proto 'infix:<' is looser('infix:..') is pirop('islt') { ... }
proto 'infix:>' is equiv('infix:<') is pirop('isgt') { ... }
proto 'infix:<=' is equiv('infix:<') is pirop('isle') { ... }
proto 'infix:>=' is equiv('infix:<') is pirop('isge') { ... }
proto 'infix:~=' is equiv('infix:<') is pirop('isne') { ... }
proto 'infix:==' is equiv('infix:<') is pirop('iseq') { ... }
proto 'infix:and' is looser('infix:<') is past('and') { ... }
proto 'infix:or' is looser('infix:and') is past('or') { ... }