antlr4 - tsql解析器:忽略未知语句

时间:2014-05-05 19:32:10

标签: tsql antlr antlr4

我是SO的新人。我想编写一个t-sql(sybase)解析器,它只能监听一些相关的sql语句。

是否可以忽略非相关语句,而无需在语法文件中编写完整的t-sql语法。因此,没有错误像第8行:第2行不匹配的输入' INSERT'期待{EXEC,BEGIN,END,IF}"来了。

我的输入是以下sql存储过程(仅示例;)):

CREATE PROCEDURE mySQL (@BaseLoglevel INT,
                    @ReleaseId INT,
                    @TargetSystem VARCHAR (5),
                    @IgnoreTimeStamp INT)                       
AS
BEGIN   
    INSERT INTO Departments
        (DepartmentID, DepartmentName, DepartmentHeadID)
        VALUES (600, 'Eastern Sales', 501)
    EXEC DoThis
    BEGIN
        EXEC DoSQLProc
    END
    if (@x=0) 
    begin
        exec DoSQL
    end
    else begin
        exec ReadTables
    end
    exec DoThat
    exec DoOther
END

因此,在我的语法文件中没有描述insert语句的内容。所以我想忽略这些未知的东西。有可能吗?

这是我的语法文件:

grammar Tsql;

/************Parser Rules*******************/
file : createProcedure sqlBlock;

createProcedure: CREATE PROC ID paramList? AS;

//Params of create procedure
paramList: LPAREN (sqlParam)(COMMA sqlParam)* RPAREN;
sqlParam: AT_SIGN ID sqlType; //(EQ defaultValue)?;
sqlType: (VARCHARTYPE | NUMERICTYPE | INTTYPE | CHARTYPE) length?;
length: LPAREN INT RPAREN;

sqlBlock : BEGIN sql* END;

sql:  sqlBlock
| sqlIf
| sqlExec               
;

sqlExec: EXEC ID (LPAREN sqlExprList? RPAREN)*  ; //SQLCall

//IF-rule
sqlIf: IF LPAREN sqlexpr RPAREN sqlIfBlock (sqlElseBlock)?;
sqlElseBlock: ELSE BEGIN sql* END;
sqlIfBlock: BEGIN sql* END;

/* T-SQL expressions */
sqlexpr
: ID LPAREN sqlExprList? RPAREN         # K
| AT_SIGN ID                            # SQLVar
| LPAREN sqlexpr RPAREN                 # SQLParens
| sqlexpr EQ INT                        # SQLEqual
| sqlexpr NOT_EQ INT                    # SQLNotEqual
| sqlexpr LTH sqlexpr                   # SQLLessThan
| sqlexpr GTH sqlexpr                   # SQLGreaterThan
| sqlexpr LEQ sqlexpr                   # SQLLessEqual
| sqlexpr GEQ sqlexpr                   # SQLGreaterEqual
| sqlexpr (PLUS|MINUS)                  # SQLAddSub
| sqlexpr (MUTLIPLY|DIVIDE)             # SQLMultDiv
| LPAREN sqlexpr RPAREN                 # SQLParens
| NOT sqlexpr                           # SQLNot
;

sqlExprList : sqlexpr (',' sqlexpr)* ;      // arg list

/************Lexer Rules*******************/
//createProcedure
CREATE : 'CREATE' | 'create';
PROC : 'PROCEDURE' | 'procedure';
AS : 'AS'|'as';
EXEC            : ('EXEC'|'exec');
//SqlTypes
INTTYPE: 'int'|'INT';
VARCHARTYPE : 'varchar'|'VARCHAR';
NUMERICTYPE : 'numeric'|'NUMERIC';
CHARTYPE : 'char'| 'CHAR';
//SqlBlock
BEGIN: 'BEGIN' | 'begin';
END: 'END' | 'end';
//If
IF: 'IF' | 'if';
ELSE : 'ELSE' | 'else';

RETURN          : ('RETURN' | 'return');
DECLARE         : ('DECLARE'|'declare');
AT_SIGN         : '@';


ID  :   LETTER (LETTER | [0-9])* ;

APOSTROPH       : [\'];
QUOTE           : ["];
LPAREN          : '(';
RPAREN          : ')';
COMMA           : ',';
SEMICOLON       : ';';
DOT             : '.';
EQ              : '=';
NOT_EQ          : ('!='|'<>');
LTH             : ('<');
GTH             : ('>');
LEQ             : ('<=');
GEQ             : ('=>');
RBRACK          : ']';
LBRACK          : '[';
PLUS            : '+';
MINUS           : '-';
MUTLIPLY        : '*';
DIVIDE          : '/';
COLON           : ':'; 

NOT             : ('NOT' | '!');

INT :   [0-9]+ ;

ML_COMMENT
:   '/*'.*? '*/' -> skip
;

SL_COMMENT
:   '//' .*? '\n' -> skip
;

WS : [ \t\r\n]+ -> skip;

fragment
LETTER : [a-zA-Z] ;

非常感谢提前。

1 个答案:

答案 0 :(得分:2)

  

是否可以忽略非相关语句,而无需在语法文件中编写完整的t-sql语法。

你可以这样做:

file
 : unit* EOF
 ;

unit
 : my_interesting_statement
 | . // any token
 ;    

my_interesting_statement
 : createProcedure sqlBlock
 | // other statements here?
 ;

// parser rules

// lexer rules

// Last lexer rule catches any character
ANY
 : .
 ;

规则file现在将匹配零个或多个unit个。 unit首先尝试匹配您的my_interesting_statement之一,如果无法匹配,unit规则中的最后一个选项.将仅匹配单个标记(右边:解析器规则中的.与单个标记匹配,不是单个字符。)

相关问题