# bibliography: # I.lex&yacc programming, ASCII, ISBN4-7561-0297-2 # II.MySQL&mSQL, O'REILLY Japan, ISBN4-87311-011-4 # III.Ruby Pocket Reference, O'REILLY Japan, ISBN4-87311-023-8 class MSQLParser prechigh left '=' left '<>' '<' '>' '<=' '>=' left AND OR preclow rule mSQL : sql_list sql_list : sql ';' | sql_list sql ';' sql : create_statement | delete_statement | drop_statement | insert_statement | select_statement | update_statement #CREATE statement create_statement : create_table_statement | create_sequence_statement | create_index_statement create_table_statement : CREATE TABLE table '(' field_def_list ')' field_def_list : field_def | field_def_list ',' field_def field_def : column data_type optional_attribute optional_attribute : /* empty */ | NOT NULL create_sequence_statement : CREATE SEQUENCE ON table optional_step optional_value optional_step : /* empty */ | STEP FIXNUM optional_value : /* empty */ | VALUE FIXNUM create_index_statement : CREATE INDEX index ON table '(' column_list ')' #DELETE statement delete_statement : DELETE FROM table optional_where_clause #DROP statement drop_statement : DROP INDEX index | DROP TABLE table | DROP SEQUENCE FROM table #INSERT statement insert_statement : INSERT INTO table optional_column_list VALUES '(' values ')' optional_column_list : /* empty */ | '(' column_list ')' values : atom_list #SELECT statement select_statement : SELECT optional_distinct_keyword column_list FROM table optional_order_by_clause optional_where_clause optional_distinct_keyword : /* empty */ | DISTINCT optional_order_by_clause : /* empty */ | ORDER BY ordering_list ordering_list : ordering | ordering_list ',' ordering ordering : column optional_desc optional_desc : /* empty */ | DESC #UPDATE statement update_statement : UPDATE table SET modify_expression_list optional_where_clause assignment_list : assignment_expression | assignment_list ',' assignment_expression assignment_expression : column '=' value value : atom #list atom_list : atom | atom_list ',' atom column_list : column_ref | column_list ',' column_ref #WHERE clause optional_where_clause : /* empty */ | where_clause where_clause : WHERE condition condition : condition AND condition | condition OR condition | '(' condition ')' | predicate predicate : comparison_predicate | like_predicate comparison_predicate : scalar_expression '=' scalar_expression | scalar_expression '<>' scalar_expression | scalar_expression '<=' scalar_expression | scalar_expression '<' scalar_expression | scalar_expression '>=' scalar_expression | scalar_expression '>' scalar_expression like_predicate : scalar_expression LIKE scalar_expression | scalar_expression RLIKE scalar_expression | scalar_expression CLIKE scalar_expression scalar_expression : atom | column_ref | '(' scalar_expression ')' #data type data_type : CHAR '(' length ')' | DATE | INT | MONEY | REAL | TEXT '(' length ')' | TIME | UINT length : FIXNUM #element atom : FIXNUM | LITERAL column : NAME column_ref : NAME | NAME '.' NAME index : NAME table : NAME end ---- header ---- # # msql.rb : generated by racc # ---- inner ---- RESERVED = ['AND', 'BY', 'CHAR', 'CLIKE', 'CREATE', 'DATE', 'DELETE', 'DESC', 'DROP', 'FROM', 'INDEX', 'INSERT', 'INT', 'INTO', 'LIKE', 'MONEY', 'NOT', 'NULL', 'ON', 'OR', 'ORDER', 'REAL', 'RLIKE', 'SELECT', 'SEQUENCE', 'SET', 'STEP', 'TABLE', 'TEXT', 'TIME', 'UINT', 'UPDATE', 'VALUE', 'VALUES', 'WHERE'] def parse( str ) @q = [] return nil if /\A\n/ =~ str while str.size > 0 do case str when /\A\s+/, /\A\n/ when /\A\d+/ @q.push [:FIXNUM, $&.to_i] when /\A\'.*\'/ s = $& @q.push [:LITERAL, s] when /\A\w+/ s = $& if RESERVED.include?(s.upcase) @q.push [eval(":#{s.upcase}"), s] else @q.push [:NAME, s] end when /\A./ s = $& @q.push [s, s] end str = $' end @q.push [false, '$'] do_parse end def next_token @q.shift end def on_error( err_tok, err_val, _values ) p err_tok, err_val, _values end ---- footer ---- parser = MSQLParser.new while line = ARGF.gets begin p parser.parse(line) rescue Racc::ParseError p $! end end