antlr4 Cymbol.g4 javac *.java run Cymbol file -gui test1.sp dot -Tpng dot.gv -o dot.png
g4
/** Simple statically-typed programming language with functions and variables * taken from "Language Implementation Patterns" book. */ grammar Cymbol; file: packageDeclaration functionDecl* 'END' ID ';'; packageDeclaration : 'CREATE' 'OR' 'REPLACE' 'PACKAGE' 'BODY' qualifiedName 'AS' ; functionDecl : 'FUNCTION' ID ('(' formalParameters? ')')? 'RETURN' oracleType 'IS' varDecl* block // FUNCTION IS_FIXED_INCOME( CUSIPID_IN IN VARCHAR2) RETURN BOOLEAN is type defs begin ... end IS_FIXED_INCOME; ; varDecl : ID oracleType ';' ; formalParameters : formalParameter (',' formalParameter)* ; formalParameter : ID 'IN'? 'OUT'? oracleType ('DEFAULT' ID)? ; subBlock: 'BEGIN' stat+ 'END' ';'; block: 'BEGIN' stat+ 'END' ID ';'; qualifiedName : ID ('.' ID)* ; oracleType : ('INT'|'NUMBER'|'VARCHAR2'|'VARCHAR'|'NVARCHAR2') ('(' DIGIT+ ')')* | ('NUMBER') ('(' DIGIT+ ',' DIGIT+ ')') | ('DATE') | ('BLOB') | ('CLOB') | ('BOOLEAN') | ('TIMESTAMP') | ('REF') ('CURSOR') | qualifiedName ('%TYPE') | qualifiedName ; stat: subBlock | if_stat | insert_stat | delete_stat | update_stat | select_stat | 'RETURN' expr? ';' | expr ':=' expr ';' // assignment | expr ';' // func call ; if_stat: 'IF' expr 'THEN' stat ('ELSIF' stat)? ('ELSE' stat)? 'END' 'IF' ';'; insert_stat: 'INSERT' .*? ';'; delete_stat: 'DELETE' .*? ';'; update_stat: 'UPDATE' .*? ';'; select_stat: 'SELECT' .*? ';'; expr: ID '(' exprList? ')' # Call | '-' expr # Negate | '!' expr # Not | expr '*' expr # Mult | expr ('+'|'-') expr # AddSub | expr '=' expr # IfCond | expr '==' expr # Equal | expr '||' expr # Contact | ID # Var | INT # Int | '\'' ID '\'' # Parens | '(' expr ')' # Parens ; exprList : expr (',' expr)* ; // arg list ID : Letter (Letter | [0-9] | '_')* ; DIGIT : [0-9]; fragment Letter : [a-zA-Z]; fragment JavaIDDigit : '\u0030'..'\u0039' | '\u0660'..'\u0669' | '\u06f0'..'\u06f9' | '\u0966'..'\u096f' | '\u09e6'..'\u09ef' | '\u0a66'..'\u0a6f' | '\u0ae6'..'\u0aef' | '\u0b66'..'\u0b6f' | '\u0be7'..'\u0bef' | '\u0c66'..'\u0c6f' | '\u0ce6'..'\u0cef' | '\u0d66'..'\u0d6f' | '\u0e50'..'\u0e59' | '\u0ed0'..'\u0ed9' | '\u1040'..'\u1049' ; INT : [0-9]+ ; WS : [ \t\n\r]+ -> skip ; SL_COMMENT : '--' .*? '\n' -> skip ; COMMENT : '/*' .*? '*/' -> channel(HIDDEN) // match anything between /* and */ ; /* varDecl : type ID ('=' expr)? ';' ; type: 'float' | 'int' | 'void' ; // user-defined types K_FLOAT : 'float'; K_INT : 'int'; K_VOID : 'void'; fragment LETTER : [a-zA-Z] ; */
test sp
CREATE OR REPLACE PACKAGE BODY ANTLR1 AS FUNCTION F1 RETURN BOOLEAN IS ASSETTYPE VARCHAR2(10); BEGIN ASSETTYPE := 'X'; BEGIN IF (ASSETTYPE = 'E') THEN RETURN FALSE; ELSE RETURN TRUE; END IF; END; ASSETTYPE := ASSETTYPE || 'YYY'; F1(); END F1; FUNCTION F2( CUSIPID_IN IN VARCHAR2 , A IN VARCHAR2) RETURN BOOLEAN IS ASSETTYPE VARCHAR2(10); BEGIN --SELECT AUTHOR INTO ASSETTYPE FROM BASELINE WHERE AUTHOR = CUSIPID_IN; IF (ASSETTYPE = 'E') THEN RETURN FALSE; ELSE RETURN TRUE; END IF; END F2; FUNCTION F3( CUSIPID_IN IN VARCHAR2 ) RETURN BOOLEAN IS ASSETTYPE VARCHAR2(10); BEGIN ASSETTYPE := '3'; --SELECT AUTHOR INTO ASSETTYPE FROM BASELINE WHERE AUTHOR = CUSIPID_IN; IF (ASSETTYPE = 'E') THEN RETURN FALSE; ELSE RETURN TRUE; END IF; F2(); END F3; FUNCTION F4( CUSIPID_IN IN VARCHAR2, V_BATCH_MODE2 OUT VARCHAR, --BATCH WS/CTF PROCESSING MODE OR NOT V_BATCH_MODE3 IN OUT VARCHAR, --BATCH WS/CTF PROCESSING MODE OR NOT V_WASH_INIT_FLAG IN BOOLEAN DEFAULT FALSE, V_ALT_LOT_NUM IN VARCHAR2 DEFAULT NULL) RETURN BOOLEAN IS ASSETTYPE VARCHAR2(10); A BOOLEAN; BEGIN ASSETTYPE := '4'; A := F3('XXX'); /* SELECT AUTHOR INTO ASSETTYPE FROM BASELINE WHERE AUTHOR = CUSIPID_IN; BEGIN UPDATE BASELINE SET ID = 1 WHERE 1 = 0; END; DELETE FROM BASELINE WHERE 1 = 0; IF (ASSETTYPE = 'E') THEN RETURN FALSE; ELSE RETURN TRUE; END IF; */ END F4; /* PROCEDURE TEST1( V_BATCH_MODE IN VARCHAR, --BATCH WS/CTF PROCESSING MODE OR NOT V_BATCH_MODE2 OUT VARCHAR, --BATCH WS/CTF PROCESSING MODE OR NOT V_BATCH_MODE3 IN OUT VARCHAR, --BATCH WS/CTF PROCESSING MODE OR NOT V_WASH_INIT_FLAG IN BOOLEAN DEFAULT FALSE, V_ALT_LOT_NUM IN VARCHAR2 DEFAULT NULL) IS TEMP_STR VARCHAR2(500); TEMP_BL BOOLEAN; BEGIN TEMP_BL := F1(); INSERT INTO Z_LARGETABLE2 ( ID, ID2 ) VALUES ( 5, 2 ); TEMP_BL := F1; TEMP_BL := IS_FIXED_INCOME('XX'); --COMM[HGHJGJG]IT; END TEST1; */ END ANTLR1;
/*** * Excerpted from "The Definitive ANTLR 4 Reference", * published by The Pragmatic Bookshelf. * Copyrights apply to this code. It may not be used to create training material, * courses, books, articles, and the like. Contact us if you are in doubt. * We make no guarantees that this code is fit for any purpose. * Visit http://www.pragmaticprogrammer.com/titles/tpantlr2 for more book information. ***/ import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.misc.MultiMap; import org.antlr.v4.runtime.misc.OrderedHashSet; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.ParseTreeWalker; import org.stringtemplate.v4.ST; import java.io.FileInputStream; import java.io.InputStream; import java.util.Set; public class Test { public static void main(String[] args) throws Exception { String inputFile = null; if ( args.length>0 ) { inputFile = args[0]; } else { // inputFile = "src/t.cymbol"; inputFile = "src/test1.sp"; } InputStream is = System.in; if ( inputFile!=null ) { is = new FileInputStream(inputFile); } ANTLRInputStream input = new ANTLRInputStream(is); CymbolLexer lexer = new CymbolLexer(input); CommonTokenStream tokens = new CommonTokenStream(lexer); CymbolParser parser = new CymbolParser(tokens); parser.setBuildParseTree(true); ParseTree tree = parser.file(); // show tree in text form System.out.println(tree.toStringTree(parser)); // Here's another example that uses StringTemplate to generate output // System.out.println(collector.graph.toST().render()); } }