#line 518 "lpsrc/flx_luademo.ipk"
include "std";
module Lua_parse
{
comment "Lua tokens";
union lua_token_t =
// mandatory terminal, code 0
| TOK_EOF
// keywords
| DO
| END
| IF
| THEN
| ELSE
| ELSEIF
| WHILE
| REPEAT
| UNTIL
| RETURN
| BREAK
| IN
| FOR
| FUNCTION
| LOCAL
| NOT
| AND
| OR
| NIL
| TRUE
| FALSE
// operators
| DOTDOT
| DOTDOTDOT
| TILDE
| EQ // =
| EQEQ // ==
| NE // ~=
| PLUS
| MINUS
| STAR
| SLASH
| CARET
| LT
| GT
| LE
| GE
// punctuation
| DOT
| COLON
| COMMA
| SEMICOLON
// brackets
| LBRACE // {
| RBRACE // }
| LPAREN // (
| RPAREN // )
| LSQ // [
| RSQ // ]
// literals
| NUMBER of double
| STRING of string
// identifier
| NAME of string
// whitespace
| WHITE
| NEWLINE
| DASHDASH_COMMENT
| SQUARE_COMMENT
;
comment "Lua lexer";
regexp digit = ['0'-'9'];
regexp lower = ['a'-'z'];
regexp upper = ['A'-'Z'];
regexp letter = lower | upper | '_';
regexp identifier = letter (letter | digit) *;
regexp quote = '\'';
regexp dquote = '"';
regexp slosh = '\\';
regexp newline = '\n';
regexp tab = '\t';
regexp space = ' ';
regexp white = tab | space;
regexp integer = digit+;
regexp fraction = '.' digit+;
regexp exponent = ('E'|'e')('+'|'-')? digit+;
regexp number = integer fraction? exponent?;
regexp hichar = [128-255];
regexp ordinary = letter | digit | hichar |
'!' | '#' | '$' | '%' | '&' | '(' | ')' | '*' |
'+' | ',' | '-' | '.' | '/' | ':' | ';' | '<' |
'=' | '>' | '?' | '@' | '[' | ']' | '^' | '_' |
'`' | '{' | '|' | '}' | '~'
;
regexp escape = slosh _ ;
regexp q_string = quote (ordinary | dquote | escape | white) * quote;
regexp dq_string = dquote (ordinary | quote | escape | white) * dquote;
regexp sq_string = "[[" _ * "]]";
keywords :=
('do',DO),
('end',END),
('if',IF),
('then',THEN),
('else',ELSE),
('elseif',ELSEIF),
('while',WHILE),
('repeat',REPEAT),
('until',UNTIL),
('return',RETURN),
('break',BREAK),
('in',IN),
('for',FOR),
('function',FUNCTION),
('local',LOCAL),
('not',NOT),
('and',AND),
('or',OR),
('nil',NIL),
('true',TRUE),
('false',FALSE),
("",TOK_EOF)
;
fun find_keyword(k:string) =
{
var i=0;
var key = keywords.[i];
until key.(0) == k or key.(0) == "" do
++i;
key = keywords.[i];
done;
return key.(1);
}
fun check_name(s:Lexer::iterator, e:Lexer::iterator) =>
let ?lexeme = Lexer::string_between (s,e) in
match find_keyword lexeme with
| TOK_EOF => NAME lexeme
| ?x => x
endmatch
;
fun numof(s:Lexer::iterator, e:Lexer::iterator) =>
let ?lexeme = Lexer::string_between (s,e) in
NUMBER (atof lexeme)
;
fun strof(s:Lexer::iterator, e:Lexer::iterator) =>
let ?lexeme = Lexer::string_between (s,e) in
STRING lexeme.[1 to -1] // hack, ignore escapes
;
fun pre_lua_lex(s:Lexer::iterator, e:Lexer::iterator) =>
reglex s to e with
| identifier => check_name(lexeme_start, lexeme_end)
| dq_string => strof(lexeme_start, lexeme_end)
| q_string => strof(lexeme_start, lexeme_end)
| number => numof(lexeme_start, lexeme_end)
| "--" .* newline => DASHDASH_COMMENT
| "+" => PLUS
| "-" => MINUS
| "*" => STAR
| "/" => SLASH
| "~" => TILDE
| ".." => DOTDOT
| "..." => DOTDOTDOT
| "=" => EQ // =
| "==" => EQEQ // ==
| "~=" => NE // ~=
| "^" => CARET
| "<" => LT
| ">" => GT
| "<=" => LE
| ">=" => GE
// punctuation
| "." => DOT
| ":" => COLON
| "," => COMMA
| ";" => SEMICOLON
// brackets
| "{" => LBRACE // {
| "}" => RBRACE // }
| "(" => LPAREN // (
| ")" => RPAREN // )
| "[" => LSQ // [
| "]" => RSQ // ]
| white + => WHITE
| newline => NEWLINE
endmatch
;
comment "Top level Lua grammar";
nonterm block:unit =
| clause* => ()
;
nonterm clause : unit =
| stat SEMICOLON => ()
| stat => ()
;
nonterm stat : unit =
| varlist1 EQ explist1 => ()
| functioncall => ()
| DO block END => ()
| WHILE exp DO block END => ()
| REPEAT block UNTIL exp => ()
| IF exp THEN block elseif_clause* else_clause? END => ()
| RETURN explist1? => ()
| BREAK => ()
| FOR NAME EQ exp COMMA_exp COMMA_exp? DO block END => ()
| FOR namelist IN explist1 DO block END => ()
| FUNCTION funcname funcbody => ()
| LOCAL FUNCTION NAME funcbody => ()
| LOCAL namelist init? => ()
;
nonterm elseif_clause : unit =
| ELSEIF exp THEN block => ()
;
nonterm else_clause : unit =
| ELSE block => ()
;
nonterm funcname : unit =
| NAME DOT_NAME* COLON_NAME? => ()
;
nonterm DOT_NAME : unit =
| DOT NAME => ()
;
nonterm COLON_NAME : unit =
| COLON NAME => ()
;
nonterm COMMA_NAME : unit =
| COMMA NAME => ()
;
nonterm COMMA_vari : unit =
| COMMA vari => ()
;
nonterm varlist1 : unit =
| vari COMMA_vari* => ()
;
nonterm namelist : unit =
| NAME COMMA_NAME* => ()
;
nonterm init : unit =
| EQ explist1 => ()
;
nonterm COMMA_exp : unit =
| COMMA exp => ()
;
nonterm explist1 : unit =
| exp COMMA_exp* => ()
;
nonterm args : unit =
| LPAREN explist1 RPAREN => ()
| LPAREN RPAREN => ()
| tableconstructor => ()
| STRING => ()
;
nonterm function : unit =
| FUNCTION funcbody => ()
;
nonterm funcbody : unit =
| LPAREN parlist1 RPAREN block END => ()
| LPAREN RPAREN block END => ()
;
nonterm parlist1 : unit =
| namelist COMMA DOTDOTDOT => ()
| namelist => ()
| DOTDOTDOT => ()
;
nonterm tableconstructor : unit =
| LBRACE fieldlist RBRACE => ()
| LBRACE RBRACE => ()
;
nonterm fieldlist : unit =
| field {fieldsep field} fieldsep? => ()
;
nonterm field : unit =
| LSQ exp RSQ EQ exp => ()
| NAME EQ exp => ()
| exp => ()
;
nonterm fieldsep : unit =
| COMMA => ()
| SEMICOLON => ()
;
// expressions
nonterm exp : unit =
| exp OR lland => ()
| lland => ()
;
nonterm lland : unit =
| lland AND comparison => ()
| comparison => ()
;
nonterm comparison : unit =
| comparison LT cat => ()
| comparison LE cat => ()
| comparison GT cat => ()
| comparison GE cat => ()
| comparison EQEQ cat => ()
| comparison NE cat => ()
| cat => ()
;
nonterm cat : unit =
| sum DOTDOT cat => ()
| sum => ()
;
nonterm sum : unit =
| sum PLUS factor => ()
| sum MINUS factor => ()
| factor => ()
;
nonterm factor : unit =
| factor STAR unary => ()
| factor SLASH unary => ()
| unary => ()
;
nonterm unary : unit =
| MINUS unary => ()
| TILDE unary => ()
| NOT unary => ()
| power => ()
;
nonterm power : unit =
| atom CARET power => ()
| atom => ()
;
nonterm atom : unit =
| NIL => ()
| FALSE => ()
| TRUE => ()
| NUMBER => ()
| STRING => ()
| tableconstructor => ()
| function => ()
| prefixexp => ()
;
nonterm prefixexp : unit =
| vari => ()
| functioncall => ()
| LPAREN exp RPAREN => ()
;
nonterm vari : unit =
| NAME => ()
| prefixexp LSQ exp RSQ => ()
| prefixexp DOT_NAME => ()
;
nonterm functioncall : unit =
| prefixexp args => ()
| prefixexp COLON_NAME args => ()
;
}