+ IN
[sqlgg.git] / sql_lexer.mll
blobf3d5986e39805f5d976b3c41ea6e070ba2712d2f
3   open Sql_parser
4   module T = Sql.Type
6   let curStr = ref ""
7   let store str = curStr := str
9 let error buf callerID =
10   Error.report "Lexer error : %s" callerID;
11 (*      update_pos buf;*)
12         raise Parsing.Parse_error
14 let advance_line_pos pos = 
15   let module L = Lexing in
16   {L.pos_fname = pos.L.pos_fname;
17    pos_lnum = pos.L.pos_lnum + 1;
18    pos_bol = pos.L.pos_cnum;
19    pos_cnum = pos.L.pos_cnum;}
21 let advance_line lexbuf = 
22   lexbuf.Lexing.lex_curr_p <- advance_line_pos lexbuf.Lexing.lex_curr_p
24 (* use Map or Hashtbl ? *)
25 let keywords = 
26   let k = ref [ 
27    "as",AS;
28    "on",ON;
29    "conflict",CONFLICT;
30    "using",USING;
31    "natural",NATURAL;
32    "join",JOIN;
33    "isnull",TEST_NULL;
34    "notnull",TEST_NULL;
35    "between",BETWEEN;
36    "and",AND;
37    "escape",ESCAPE;
38    "not",NOT;
39    "null",NULL;
40    "unique",UNIQUE;
41    "primary",PRIMARY;
42    "key",KEY;
43    "autoincrement",AUTOINCREMENT;
44    "default",DEFAULT;
45    "text",T_TEXT;
46    "integer",T_INTEGER;
47    "int",T_INTEGER;
48    "blob",T_BLOB;
49 (*    CHARACTER, CHARACTER VARYING, BIT, BIT VARYING, NUMERIC, DECIMAL,
50          INTEGER, SMALLINT, FLOAT, REAL, DOUBLE PRECISION, DATE, TIME,
51          TIMESTAMP, and INTERVAL.*)
52    "distinct",DISTINCT;
53    "all",ALL;
54    "order",ORDER;
55    "by",BY;
56    "limit",LIMIT;
57    "desc",DESC;
58    "asc",ASC;
59    "offset",OFFSET;
60    "select",SELECT;
61    "create",CREATE;
62    "table",TABLE;
63    "insert",INSERT;
64    "replace",REPLACE;
65    "update",UPDATE;
66    "delete",DELETE;
67    "from",FROM;
68    "or",OR;
69    "into",INTO;
70    "values",VALUES;
71    "where",WHERE;
72    "from",FROM;
73    "set",SET;
74    "in",IN;
75    "group",GROUP;
76    "having",HAVING;
77   ] in
78   let all token l = k := !k @ List.map (fun x -> x,token) l in
79   all (FUNCTION (Some T.Int)) ["max"; "min"; "length"; "random";"count"];
80   all (FUNCTION (Some T.Text)) ["concat";];
81   all CONFLICT_ALGO ["ignore"; "replace"; "abort"; "fail"; "rollback";];
82   all JOIN_TYPE1 ["left";"right";"full"];
83   all JOIN_TYPE2 ["inner";"outer";"cross"];
84   all LIKE_OP ["like";"glob";"regexp";"match"];
85   !k
87 let keywords = List.map (fun (k,v) -> (String.lowercase k, v)) keywords
89 let get_ident str =
90   let str = String.lowercase str in
91   try List.assoc str keywords with Not_found -> IDENT str 
94 let digit = ['0'-'9']
95 let alpha = ['a'-'z' 'A'-'Z']
96 let ident = (alpha) (alpha | digit | '_' )*
97 let wsp = [' ' '\r' '\t']
99 rule ruleStatement props = parse
100   | ['\n' ' ' '\r' '\t']+ { ruleStatement props lexbuf }
101 (* fixme strings *)
102   | "--" wsp* "[sql2cpp]" wsp+ (ident+ as n) wsp* "=" wsp* ([^'\n']* as v) '\n' 
103       { 
104         ruleStatement (Props.set props n v) lexbuf
105       }
106   | "--" { store ""; ignore (ruleComment lexbuf); ruleStatement props lexbuf }
107   | alpha [^ ';']+ as stmt ';' { Some (stmt,props) }
108   | _ { None }
110 ruleMain = parse
111   | wsp   { ruleMain lexbuf }
112   (* update line number *)
113   | '\n'  { advance_line lexbuf; ruleMain lexbuf}
115   | '('         { LPAREN }
116   | ')'         { RPAREN }
117   | ','   { COMMA }
118   | '.'   { DOT }
120   | "--" { store ""; ignore (ruleComment lexbuf); ruleMain lexbuf }
121 (*  | '"' { store ""; ruleInQuotes lexbuf } *)
123   | "UNION" (wsp+ "ALL")? | "EXCEPT" | "INTERSECT" { COMPOUND_OP }
125   | "*" { ASTERISK }
126   | "=" { EQUAL }
127   | "!" { EXCL }
128   | "~" { TILDE }
129   | "||" { CONCAT_OP }
130   | "+" { PLUS }
131   | "-" { MINUS }
133   | "/" | "%" | ">" | ">=" | "<=" | "<" | "&" | "|" { NUM_BINARY_OP }
135   | "?" { PARAM Stmt.Next }
136   | "?" (digit+ as str) { PARAM (Stmt.Numbered (int_of_string str)) }
137   | [':' '@'] (ident as str) { PARAM (Stmt.Named str) }
139   | "'" { TEXT (ruleInSingleQuotes "" lexbuf) }
140   | ['x' 'X'] "'" { BLOB (ruleInSingleQuotes "" lexbuf) }
142   | ident as str { get_ident str }
143   | digit+ as str { INTEGER (int_of_string str) }
144   | eof         { EOF }
145   | _           { error lexbuf "ruleMain" }
146 and 
147 ruleInSingleQuotes acc = parse
148   | '\''              { acc }
149   | eof         { error lexbuf "no terminating quote" }
150   | '\n'        { advance_line lexbuf; error lexbuf "EOL before terminating quote" }
151   | "''"        { ruleInSingleQuotes (acc ^ "'") lexbuf }
152   | [^'\'' '\n']+  { ruleInSingleQuotes (acc ^ Lexing.lexeme lexbuf) lexbuf }
153   | _           { error lexbuf "ruleInSingleQuotes" }
155 ruleComment = parse
156   | '\n'              { advance_line lexbuf; !curStr }
157   | eof         { !curStr }
158   | [^'\n']+    { store (Lexing.lexeme lexbuf); ruleComment lexbuf; }
159   | _           { error lexbuf "ruleComment"; }
163   let parse_rule lexbuf = ruleMain lexbuf