Docs GODI Archive
Projects Blog Link DB

Search GODI:


More options
File lib/felix/lib/lua_parse.flx GODI Package apps-felix
 
   lua_parse.flx  
#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 => ()
  ;

}


This web site is published by Informatikbüro Gerd Stolpmann
Powered by Caml