我是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] ;
非常感谢提前。
答案 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
规则中的最后一个选项.
将仅匹配单个标记(右边:解析器规则中的.
与单个标记匹配,不是单个字符。)