// Import the necessary classes { import java.io.*; import antlr.*; import uk.ac.sheffield.dcs.dfa.*; import uk.ac.sheffield.dcs.dfa.spec.*; } class ANTLRSyntax100 extends Parser; options { k = 4; // four token lookahead exportVocab=DFA; // Call its vocabulary "DFA" // codeGenMakeSwitchThreshold = 2; // Some optimizations //codeGenBitsetTestThreshold = 3; //defaultErrorHandler = false; // Don't generate parser error handlers buildAST = true; } { private int CurrentType; public TokenStreamSelector selector; private uk.ac.sheffield.dcs.dfa.SyntaxInterface sn; private uk.ac.sheffield.dcs.dfa.PostprocessorInterface currentPostprocessor; public void setParent(uk.ac.sheffield.dcs.dfa.SyntaxInterface sn) { this.sn = sn; } private PostprocessorSyntaxInterface getPostprocessorSyntax() { TokenStreamSelector selector = sn.getSelector(); //Postprocessor Access Point PostprocessorSyntaxInterface si = currentPostprocessor.getSyntax(); PostprocessorLexerInterface li = currentPostprocessor.getLexer(); //ZSpecLexer lexer = new ZSpecLexer(getInputState()); li.initialise(sn.getLexer().getInputState(), selector); selector.addInputStream((antlr.CharScanner)li.getLexer(), "zspec"); selector.push((antlr.CharScanner)li.getLexer()); si.initialise(selector, getFilename(), getInputState()); return si; } } document : sections SYMFULLSTOP! EOF!; //sections : PRNPROGRAM LPAREN word RPAREN; sections : (section)+; section : topology | syntax | semantics | program | info ; topology : PRNTOPOLOGY^ topologybody PRNEND! ; syntax : PRNSYNTAX^ syntaxbody PRNEND!; semantics : PRNSEMANTICS^ LPAREN! S:word RPAREN! { //Loadup relevent Postprocessor, via the postprocessor factory. currentPostprocessor = sn.getPostprocessor(S_AST.getText()); } semanticbody PRNEND!; program : PRNPROGRAM^ LPAREN! S:word RPAREN! { //Loadup relevent Postprocessor, via the postprocessor factory. currentPostprocessor = sn.getPostprocessor(S_AST.getText()); } programbody PRNEND!; type { CurrentType = 0; } : PRNPROC {CurrentType = PRNPROC;} | PRNCHAN {CurrentType = PRNCHAN;} | PRNACT {CurrentType = PRNACT;} | PRNSEQ {CurrentType = PRNSEQ;} // | {CurrentType = PRNATT;} PRNATT // | PRNANAME{CurrentType = PRNANAME;} | PRNINT {CurrentType = PRNINT;} // | PRNBOOL {CurrentType = PRNBOOL;} | {CurrentType = PRNSPEC;} PRNSPEC ; filedecl! : PRNFILE! A:FILESTRING PREND! {#filedecl = #([PRNFILE], A);} ; declation! : A:type B:declation1 {#declation = #(A, B);} ; declation1 : declation2 SYMFULLSTOP! ; declation2 : declation3 (SYMCOMMA! declation3)* ; declation3 : declationbit ; //declations : (declationbit SYMCOMMA)* declationbit SYMFULLSTOP; declationbit! : A:declationname (SYMEQUALS! B:declationstring)? {#declationbit = #([VIRDEC, "declaration"], ([NOTHING, "head"], A),([NOTHING, "body"], B));} ; declationname! : A:dname (SYMSQLEFT! B:subscriptdeclarations SYMSQRIGHT!)? {#declationname = #([VIRDECNAMEA, "declationname-A"], A, B);} | C:ifconst {#declationname = #([VIRDECNAMEB, "declationname-B"], C);} ; //deal with expressions here, beacuse its less confusing (proportional speaking) subscriptdeclarations! : (word SYMEQUALS)=> A:word SYMEQUALS! B:expr SYMCOLON! C:expr {#subscriptdeclarations = #([VIRSUBSCRIPTA, "subscript-A"], A, ([VIREXPR, "expr"],B), ([VIREXPR, "expr"],C));} | (expr SYMCOLON)=> D:expr SYMCOLON! E:expr {#subscriptdeclarations = #([VIRSUBSCRIPTB, "subscript-B"], ([VIREXPR, "expr"],D), ([VIREXPR, "expr"],E));} | F:expr {#subscriptdeclarations = #([VIRSUBSCRIPTC, "subscript-C"], ([VIREXPR, "expr"],F));} ; subscriptdeclaration : SYMSQLEFT! subscriptdeclarations SYMSQRIGHT! ; declationstring : {CurrentType == PRNINT}? INT | {CurrentType == PRNACT}? actdecl | {CurrentType == PRNSPEC}? specvalue | {CurrentType == PRNSEQ}? sequence // | {CurrentType == PRNATT}? attexpr ; dname : A:word (SYMDOLLAR! { //init lexer and syntax - build ast A_AST.addChild(getPostprocessorSyntax().parseAtributeName()); //return to old lexer selector.pop(); } )? ; //this needs a semantic check //attributename // : "Src" // | "Dest" // | "States" // | "DataType" // | "ProcSpec" // | word // ; array : PRNARRAY^ A:type SYMFULLSTOP! ; ifconst : ifstart ifmid {#ifconst = #([PRNIF, "IF"], #ifconst);} ; ifmid : ifelseif ifmid | ifelse ifend ; ifstart : PRNIF! condition PRNTHEN! declationname ; ifend : PRNFI! ; ifelse : PRNELSE^ declationname ; ifelseif : PRNELSF^ condition PRNTHEN! declationname ; //Should condistions beable to handel boolean values? condition : word (SYMEQUALS^ | SYMEVAL^) wordornumber ; //TOPOLOGY topologybody : (declation)* ; actdecl! : EMPTYACTION! {#actdecl = #[EMPTYACTION];} | FORBIDENACTION! {#actdecl = #[FORBIDENACTION];} | A:declationname SYMEXCLAMATION! B:declationname SYMQUESTION! C:declationname {#actdecl = #([PRNACT, "ACT"], ([VIRACTIN,"IN"],A),([VIRACTCHAN,"CHAN"],B),([VIRACTOUT,"OUT"],C));} ; //SYNTAX syntaxbody : (declation)*; //syntaxpart : declation; //defs for sequences //sopensym : SYMLCURLY; //sclosesym : SYMRCURLY; //sinsym : SYMEQUALS; //altsym : SYMPIPE; //seqsym : SYMSEMICOLON; sequence : parexp; //reordered to make pars bind losest parexp : cparexp (PAR! cparexp)* {#parexp = #([PAR, "SEQ-PAR"], #parexp);} ; cparexp : altexp (CPAR! altexp SYMFSLASH! constraintsequenceset)* {#cparexp = #([CPAR, "SEQ-CPAR"], #cparexp);} ; altexp : seqexp (ALT! seqexp)* {#altexp = #([ALT, "SEQ-ALT"], #altexp);} ; seqexp : brack (SEQ! brack)* {#seqexp = #([SEQ, "SEQ-SEQ"], #seqexp);} ; brack : seqconst | LPAREN! parexp RPAREN! ; seqconst : declationname | sigmadecl | uniondecl | pidecl | picdecl | dodecl | inlineact; inlineact : PRNACT^ actdecl ; sigmadecl : PRNSIGMA^ subscriptdeclaration PRNOVER! sequence PRNEND! ; uniondecl : PRNUNION^ subscriptdeclaration PRNOVER! sequence PRNEND! ; pidecl : PRNPI^ subscriptdeclaration PRNOVER! sequence PRNEND! ; picdecl : PRNPIC^ subscriptdeclaration PRNOVER! sequence SYMFSLASH! constraintsequenceset PRNEND! ; //check right constraintsequenceset! : SYMLCURLY! A:scs1 SYMRCURLY! {#constraintsequenceset = #([VIRCONSTRAINT, "CONSTRAINT"], A);} ; scs1 : sequence (SYMCOMMA! sequence)* ; // Where are do loops used? // What is the meaning of it, in sysntax this is covered by sigma? dodecl : PRNDO^ sequence dotype PRNOD! ; //just to limit the number of iterations dotype : PRNFOR^ wordornumber | PRNBY^ doby ; doby : SYMPLUS | SYMSTAR ; semanticbody : (attexpr | declation | processspec | definition)*; //semanticpart : processspec | declation; processspec : PRNFROM^ FILESTRING SYMFULLSTOP!; //Postprocessor Access Point specvalue : A:PRNBEGIN^ { //init lexer and syntax - build ast A_AST.addChild(getPostprocessorSyntax().parsePartialSpecification()); //return to old lexer selector.pop(); } ; //partialspec : word; attexpr : PRNATT^ attpart (SYMCOMMA attpart)* SYMFULLSTOP! ; attpart! : (word SYMEQUALS)=>A:word B:SYMEQUALS { //init lexer and syntax - build ast B_AST.addChild(getPostprocessorSyntax().parseAtributeExpr()); //return to old lexer selector.pop(); } {#attpart = #([VIRDEC, "ATTDeclration"], ([NOTHING, "head"],([VIRDECNAMEA, "VIRDECNAMEA"], A)),([NOTHING, "body"], B));} | (word SYMDOLLAR)=>C:word D:SYMDOLLAR { //init lexer and syntax - build ast D_AST.addChild(getPostprocessorSyntax().parseAtributeName()); //return to old lexer selector.pop(); } SYMEQUALS! E:word {#attpart = #([VIRDEC, "ATTDeclration"], ([NOTHING, "head"], ([VIRDECNAMEA, "VIRDECNAMEA"],C, D)),([NOTHING, "body"], E));} ; definition : A:PRNDEF^ { //init lexer and syntax - build ast A_AST.addChild(getPostprocessorSyntax().parseDefinition()); //return to old lexer selector.pop(); } SYMFULLSTOP! ; programbody : ((evaluate | evaluatesil) SYMFULLSTOP!)*; //postprocessr to handle this evaluate : A:PRNTO^ FILESTRING PRNOUT! { //init lexer and syntax - build ast A_AST.addChild(getPostprocessorSyntax().parseProgramArguments()); //return to old lexer selector.pop(); } PRNEND! ; //postprocessr to handle this evaluatesil : A:PRNSILENT^ { //init lexer and syntax - build ast A_AST.addChild(getPostprocessorSyntax().parseProgramArguments()); //return to old lexer selector.pop(); } PRNEND! ; //commentline : DIRCOMMENTSINGLE properstring!; //commentmulti : DIRCOMMENTLEFT commentmultiinner DIRCOMMENTRIGHT; //commentmultiinner : properstring (commentmulti)*; //commentmultiinners : properstring; //commentmulti | info : hash | version; hash : HASHSTRING^; //include : DIRINCLUDE^ confilename; version : PRNVERSION^ LPAREN! INT SYMMINUS! INT SYMMINUS! INT RPAREN! SYMFULLSTOP!; //PRNVERSION^ LPAREN! versionstring RPAREN!; //some handy constructs number : INT ; word : ALPHA ; //anstring : // ; wordornumber : ALPHA | INT; sum : wordornumber SYMPLUS wordornumber | wordornumber SYMMINUS wordornumber ; // TODO add head node expr : wordornumber | wordornumber SYMPLUS wordornumber | wordornumber SYMMINUS wordornumber ; versionstring : (INT | ALPHA | SYMMINUS | SYMFULLSTOP)+ ; //confilename : SYMQUOTE anstring SYMFULLSTOP anstring SYMQUOTE // ; ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// { import java.io.*; import antlr.*; } class ANTLRLexer100 extends Lexer; options { exportVocab = DFA; // call the vocabulary "Pascal" k = 8; // four characters of lookahead caseSensitive = true; } tokens { NOTHING; PRNPROC = "PROC"; PRNCHAN = "CHAN"; PRNACT = "ACT"; PRNSEQ = "SEQ"; PRNATT = "ATT"; PRNANAME = "ANAME"; PRNINT = "INT"; PRNBOOL = "BOOL"; PRNSPEC = "SPEC"; PRNTOPOLOGY = "TOPOLOGY"; PRNSYNTAX = "SYNTAX"; PRNSEMANTICS = "SEMANTICS"; PRNPROGRAM = "PROGRAM"; PRNVERSION = "VERSION"; PRNEND = "END"; PRNFILE = "FILE"; PRNARRAY = "ARRAY OF"; PRNIF = "IF"; PRNTHEN = "THEN"; PRNELSE = "ELSE"; PRNELSF = "ELSF"; PRNFI = "FI"; PRNOVER = "OVER"; PRNSIGMA = "SIGMA"; PRNUNION = "UNION"; PRNPI = "PI"; PRNDO = "DO"; PRNOD = "OD"; PRNFOR = "FOR"; PRNBY = "BY"; PRNPIC = "PIC"; PRNFROM = "FROM"; PRNBEGIN = "BEGIN"; PRNSILENT = "SILENT"; PRNTO = "TO"; PRNOUT = "OUT"; PRNDEF = "DEF"; PRNMULTI = "MULTI"; //DIRINCLUDE = "INCLUDE"; //DIRCOMMENTSINGLE = "--"; //DIRCOMMENTLEFT = "(*"; //DIRCOMMENTRIGHT = "*)"; FORBIDENACTION = "EPS"; EMPTYACTION = "PHI"; // tokens for the AST (ie they are virtual) VIRTYPE = "TYPE"; VIRSUBSCRIPTA = "SUBSCRIPT-A"; VIRSUBSCRIPTB = "SUBSCRIPT-B"; VIRSUBSCRIPTC = "SUBSCRIPT-C"; VIRACTIN = "ACT-IN"; VIRACTCHAN = "ACT-CHAN"; VIRACTOUT = "ACT-OUT"; VIRDEC = "DECLARATION"; VIRDECNAMEA = "DECLARATION-NAME-A"; VIRDECNAMEB = "DECLARATION-NAME-B"; VIRCONSTRAINT = "CONSTRAINTSET"; VIREXPR = "EXPRESION"; } { public void uponEOF() throws TokenStreamException, CharStreamException { if ( lx.getSelector().getCurrentStream() != lx.getLexer() ) { // don't allow EOF until main lexer. Force the // selector to retry for another token. lx.getSyntax().setFilename(lx.getLexer().getFilename()); uk.ac.sheffield.dcs.dfa.util.DFAToolASTNode.setCurrentFilename(lx.getLexer().getFilename()); lx.getSelector().pop(); // return to old lexer/stream lx.getSelector().retry(); } else { // System.out.println("Hit EOF of main file"); } } private uk.ac.sheffield.dcs.dfa.LexerInterface lx; public void setParent(uk.ac.sheffield.dcs.dfa.LexerInterface lx) { this.lx = lx; } } INCLUDE : "INCLUDE" (WS)? f:FILESTRING SYMFULLSTOP { // create lexer to handle include String name = f.getText(); //only parse the file if it has not already been parsed if (lx.addfile(name)) { DataInputStream input=null; try { FileInputStream fi = new FileInputStream(name); input = new DataInputStream(fi); ANTLRLexer100 sublexer = new ANTLRLexer100(input); // make sure errors are reported in right file sublexer.setParent(lx); sublexer.setFilename(name); lx.getSyntax().setFilename(name); uk.ac.sheffield.dcs.dfa.util.DFAToolASTNode.setCurrentFilename(name); // you can't just call nextToken of sublexer // because you need a stream of tokens to // head to the parser. The only way is // to blast out of this lexer and reenter // the nextToken of the sublexer instance // of this class. lx.getSelector().push(sublexer); // ignore this as whitespace; ask selector to try // to get another token. It will call nextToken() // of the new instance of this lexer. lx.getSelector().retry(); // throws TokenStreamRetryException } catch (FileNotFoundException fnf) { System.err.println(getFilename()+":"+getLine()+": Cannot find file: "+name); } } lx.getSelector().retry(); } ; WS options { paraphrase = "some whitespace"; } : ( ' ' | '\t' | '\r' '\n' {newline();} | '\r' {newline();} | '\n' {newline();} ) { _ttype = Token.SKIP; } ; SYMAT : '@'; LPAREN options { paraphrase = "a left bracket"; } : '(' ; RPAREN options { paraphrase = "a right bracket"; } : ')' ; ALT options { paraphrase = "a alt symbol"; } : "|" ; PAR options { paraphrase = "a parallel composition symbol"; } : "||" ; CPAR options { paraphrase = "a constrained parallel composition symbol"; } : "|/|" | "||c" ; SEQ options { paraphrase = "a sequence composition symbol"; } : ';' ; SYMCOLON options { paraphrase = "a colon"; } : ':' ; SYMCOMMA options { paraphrase = "a semicolon"; } : ',' ; SYMFULLSTOP options { paraphrase = "a fullstop"; } : '.' ; SYMQUOTE options { paraphrase = "a doublequote"; } : '"' ; SYMQUESTION options { paraphrase = "a question mark"; } : '?' ; SYMEXCLAMATION options { paraphrase = "a exclamation mark"; } : '!' ; //SYMPIPE : '|'; SYMEQUALS options { paraphrase = "a equals symbol"; } : '=' ; SYMSQLEFT options { paraphrase = "a left square bracket"; } : '[' ; SYMSQRIGHT options { paraphrase = "a right square bracket"; } : ']' ; SYMPLUS options { paraphrase = "a plus symbol"; } : '+' ; SYMMINUS options { paraphrase = "a minus symbol"; } : '-' ; SYMSTAR options { paraphrase = "a star"; } : '*' ; SYMFSLASH options { paraphrase = "a forward slash"; } : '/' ; SYMDOLLAR options { paraphrase = "a dollar symbol"; } : '$' ; SYMLCURLY options { paraphrase = "a left curly bracket"; } : '{' ; SYMRCURLY options { paraphrase = "a right curly bracket"; } : '}' ; //SYMHASH : '#'; //SYMSEMICOLON : ';'; SYMEVAL options { paraphrase = "a evaluation symbol"; } : '<' | '>' | "<=" | ">=" ; INT : ('0'..'9')+ ; ALPHA options {testLiterals=true;} : ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')* ; FILESTRING : '"'! ( ~'"' )* '"'! ; HASHSTRING options { paraphrase = "a hash string"; } : '#' ( ~('\n' | '\r') )*!; COMMENT_1 options { paraphrase = "a multiline comment"; } { int bracketCount = 0; } : "(*" ( options { generateAmbigWarnings=false; } : {bracketCount != 0}? '*' ')' {bracketCount--;} | { LA(2) != ')' }? '*' | '\r' '\n' {newline();} | '\r' {newline();} | '\n' {newline();} | '(''*' {bracketCount++;} | ~('*' | '\n' | '\r') )* "*)" {$setType(Token.SKIP);} ; // Any line which has part of a multiline comment on it, which opened in a single // line comment will be treated as a line which is totaly filled by the single // line comment. COMMENT_2 options { paraphrase = "a single line comment"; } { int bracketCount = 0; } : "--" ( options { generateAmbigWarnings=false; } : {bracketCount != 0}? '*' ')' {bracketCount--;} | { LA(2) != ')' }? '*' | {bracketCount != 0}? '\r' '\n' {newline();} | {bracketCount != 0}?'\r' {newline();} | {bracketCount != 0}?'\n' {newline();} | '(''*' {bracketCount++;} | ~('*' | '\n' | '\r') )* {$setType(Token.SKIP);} ; /////////////////////////////////////////////////////////////////////////////////////// // // // /////////////////////////////////////////////////////////////////////////////////////// /* class ANTLRTreeWalker extends TreeParser; { //Some data structures to get us started private HashMap varible; } document //returns [HashMap v] : parts* ; parts : #(PRNTOPOLOGY topology_def) | #(PRNSYNTAX syntax_def) | #(PRNSEMANTICS semantics_def) | #(PRNPROGRAM program_def) | #(HASHSTRING) | #(PRNVERISON version_def) | #(PRNINCLUDE include_def) ; topology_def { type } : declarations* ; declarations : #(PRNPROC decl_chunk) | #(PRNCHAN decl_chunk) | #(PRNACT decl_chunk) | #(PRNSEQ decl_chunk) | #(PRNATT decl_chunk) | #(PRNANAME decl_chunk) | #(PRNINT decl_chunk) | #(PRNBOOL decl_chunk) | #(PRNSPEC decl_chunk) ; */