options { STATIC = false; } PARSER_BEGIN(CApproxParser) package tmp.generated_capprox; import java.io.*; import java.util.*; import cide.gast.*; import cide.gparser.*; public class CApproxParser{ // Run the parser public static void main ( String args [ ] ) { CApproxParser parser ; if(args.length == 0){ System.out.println("C (approx) Parser Version 0.1Alpha: Reading from standard input . . ."); parser = new CApproxParser(new OffsetCharStream(System.in)); } else if(args.length == 1){ System.out.println("C (approx) Parser Version 0.1Alpha: Reading from file " + args[0] + " . . ." ); try { parser = new CApproxParser(new OffsetCharStream(new java.io.FileInputStream(args[0]))); } catch(java.io.FileNotFoundException e){ System.out.println("C (approx) Parser Version 0.1: File " + args[0] + " not found."); return ; } } else { System.out.println("C (approx) Parser Version 0.1Alpha: Usage is one of:"); System.out.println(" java CParser < inputfile"); System.out.println("OR"); System.out.println(" java CParser inputfile"); return ; } try { parser.TranslationUnit(); System.out.println("C (approx) Parser Version 0.1Alpha: Java program parsed successfully."); } catch(ParseException e){ System.out.println("C (approx) Parser Version 0.1Alpha: Encountered errors during parse."); e.printStackTrace(); } } public ISourceFile getRoot() throws ParseException { return TranslationUnit(); } /** * Append the given {@link Token} and any preceding special tokens to a * given {@link StringBuffer}. * * @param token the given JavaCC {@link Token} object * @param buffer the buffer to which to append token **/ final private static void accumulate (Token token, StringBuffer buffer) { // Append preceding special tokens to buffer: // Token special = firstSpecial (token) ; if (special != token) while (special != null) { buffer.append (special.toString ()) ; special = special.next ; } // Finally, append the token itself: // buffer.append (token.toString ()) ; } /** * Accumulate {@list Token} objects from the token stream, respecting * nested code inside open and close pairs, * until an unmatched close is the next token in the stream. * This method assumes that an open token has just been read * from the stream so the initial nesting level is 1. The method returns * when a matching close token is the next token in the token * stream. The close token is left in the stream! * * @return the accumulated tokens as a {@link String}. * * @throws ParseException * if an end-of-file is found before an unmatched close token. **/ final private Token accumulateNestedRegion (int open, int close) throws ParseException { StringBuffer buffer = new StringBuffer () ; // Initialize result with known information (starting position, etc.): // Token result = Token.newToken (OTHER) ; result.specialToken = null ; Token startToken = firstSpecial (getToken (1)) ; result.beginColumn = startToken.beginColumn ; result.beginLine = startToken.beginLine ; // Accumulate tokens until a close token is found: // for (int nesting = 1 ; nesting > 0 ; ) { getNextToken () ; // Update information in result: // result.endColumn = token.endColumn ; result.endLine = token.endLine ; result.next = token.next ; if (token.kind == EOF) throw new ParseException ( "accumulating from line " + result.beginLine + " at column " + result.beginColumn + ": EOF reached before ending " + tokenImage [close] + " found" ) ; accumulate (token, buffer) ; if (token.kind == open) ++ nesting ; else if (token.kind == close) { if (nesting == 1) break ; -- nesting ; } } result.image = buffer.toString () ; return result ; } /** * Accumulate {@link Token} objects from the token stream until a token * matching tokenKind is consumed from the stream. The * tokens are accumulated in buffer, including the terminating * token. * * @return a {@link Token} * formed by concatenating all intervening tokens and special tokens. **/ final private Token accumulateUntilToken (int tokenKind) throws ParseException { StringBuffer buffer = new StringBuffer () ; Token token = getNextToken () ; // Initialize result with known information (starting position, etc.): // Token result = Token.newToken (OTHER) ; result.specialToken = null ; Token startToken = firstSpecial (token) ; result.beginColumn = startToken.beginColumn ; result.beginLine = startToken.beginLine ; // Accumulate tokens until a tokenKind token is found: // while (token.kind != tokenKind) { // Update information in result: // result.endColumn = token.endColumn ; result.endLine = token.endLine ; result.next = token.next ; if (token.kind == EOF) throw new ParseException ( "from line " + result.beginLine + " at column " + result.beginColumn + ": EOF reached before " + tokenImage [tokenKind] + " found" ) ; accumulate (token, buffer) ; token = getNextToken () ; } accumulate (token, buffer) ; result.image = buffer.toString () ; return result ; } /** * finds the end of the current line for preprocessor instructions. handles * also multiline makros ending with \ * * @return * @throws ParseException */ final private Token accumulateUntilLineEnd() throws ParseException { StringBuffer buffer = new StringBuffer(); Token nextToken = peekNext(); // Initialize result with known information (starting position, etc.): // Token result = Token.newToken(OTHER); result.specialToken = null; Token startToken = firstSpecial(nextToken); result.beginColumn = startToken.beginColumn; result.beginLine = startToken.beginLine; // Accumulate tokens until a tokenKind token is found: // while (!preceededByLinebreak(nextToken) || token.image.equals("\\")) { getNextToken(); // Update information in result: // result.endColumn = token.endColumn; result.endLine = token.endLine; result.next = token.next; if (token.kind == EOF) throw new ParseException("from line " + result.beginLine + " at column " + result.beginColumn + ": EOF reached before special token" + " found"); accumulate(token, buffer); nextToken = peekNext(); } result.image = buffer.toString(); return result; } private boolean preceededByLinebreak(Token t) { assert t != null; Token specialToken = t.specialToken; while (specialToken != null) { if (specialToken.image.indexOf('\n')>=0) return true; specialToken = specialToken.specialToken; } return false; } private Token peekNext() { if (token.next == null) token.next = token_source.getNextToken(); return token.next; } /** * Finds the first token, special or otherwise, in the list of special * tokens preceding this {@link Token}. If this list is non-empty, the * result will be a special token. Otherwise, it will be the starting * token. * * @param token the given {@link Token}. * @return the first special token preceding token. **/ final private static Token firstSpecial (Token token) { while (token.specialToken != null) token = token.specialToken ; return token ; } } PARSER_END(CApproxParser) SPECIAL_TOKEN : { "\n" } SKIP : { " " | "\t" | "\r" //| "\n" | <"//" (~["\n","\r"])* ("\n" | "\r" | "\r\n")> | <"/*" (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/"> | <"__attribute__((" (~[")"])* "))"> | <"__attribute__((format(" (~[")"])* ")))"> } TOKEN : { | | |> | <#INTEGER_LITERAL: (["l","L"])? | (["l","L"])? | (["l","L"])?> | <#DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])*> | <#HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+> | <#OCTAL_LITERAL: "0" (["0"-"7"])*> | <#FLOATING_POINT_LITERAL: (["0"-"9"])+ "." (["0"-"9"])* ()? (["f","F","d","D"])? | "." (["0"-"9"])+ ()? (["f","F","d","D"])? | (["0"-"9"])+ (["f","F","d","D"])? | (["0"-"9"])+ ()? ["f","F","d","D"]> | <#EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+> | <#CHARACTER_LITERAL: "\'" (~["\'","\\","\n","\r"] | "\\" (["n","t","b","r","f","\\","\'","\""] | ["0"-"7"] (["0"-"7"])? | ["0"-"3"] ["0"-"7"] ["0"-"7"])) "\'"> | <#STRING_LITERAL: "\"" ( ~["\"","\\","\n","\r"] | "\\" ( ["n","t","b","r","f","\\","\'","\""] | ["0"-"7"] (["0"-"7"])? | ["0"-"3"] ["0"-"7"] ["0"-"7"] | ( ["\n","\r"] | "\r\n")))* "\""> } TOKEN : { | | | | | | | | | | | //| //| | | | | | | | | | | | | | | | | | | | | | | | | "> | | | | | | | } TOKEN : { ( | )* | "long long"> | <#LETTER: ["$","A"-"Z","_","a"-"z"]> | <#DIGIT: ["0"-"9"]> | } JAVACODE Token findEndGT () { return accumulateNestedRegion (LT, GT) ; } JAVACODE Token findLineEnd () { return accumulateUntilLineEnd() ; } JAVACODE Token findEndCB () { return accumulateNestedRegion(OB, CB) ; } JAVACODE Token findEndCCB () { return accumulateNestedRegion(OCB, CCB) ; } GRAMMARSTART TranslationUnit: Sequence_CodeUnit_TopLevel ; Sequence_CodeUnit_TopLevel: (LL(2) CodeUnit_TopLevel @!)*; CodeUnit_TopLevel: LL(2) PPIncludeStatement :: Include | LL(2) PPDefineStatement :: Define | LL(2) PPIfDef_TopLevel :: IfDefTL | LL(2) "#" PPOtherIgnore JAVATOKEN(findLineEnd) @! :: Preprocessor | LL("FunctionHeader()") Function :: Func | TypeDef :: TypeDef_ | LL(3) ExternDecl :: ExternDec | Statement :: StmtTL; CodeUnit_InBlock: LL(2) PPIfDef_BlockLevel :: IfDefBL | LL(2) PPIncludeStatement :: IncludeBL | LL(2) PPDefineStatement :: DefineBL | LL(2) "#" PPOtherIgnore JAVATOKEN(findLineEnd) @! :: PreprocessorBL | LL(1) IfStatement :: If | LL(1) ForStatement :: For | LL(1) WhileStatement :: While | LL(1) DoStatement :: Do | LL(1) SwitchStatement :: Switch | LL(2) GotoLabel | LL(1) Block :: Blck | Statement :: Stmt; Statement: (AnyStmtToken)* ";" @!; IfStatement: "if" "(" JAVATOKEN(findEndCB) BlockOrSingleStatement [ LL(1) ElseBlock ]; ElseBlock: "else" ;//[ LL(1) BlockOrSingleStatement ]; ForStatement: "for" "(" JAVATOKEN(findEndCB) @+! BlockOrSingleStatement @-; WhileStatement: "while" "(" JAVATOKEN(findEndCB) @+! BlockOrSingleStatement @-; DoStatement: "do" @+! BlockOrSingleStatement @-! "while" "(" JAVATOKEN(findEndCB) ";" @!; SwitchStatement: "switch" "(" JAVATOKEN(findEndCB) "{" @+! (SwCase)* @- "}"; SwCase: "default" ":" Sequence_CodeUnit_InBlock @! | "case" [LL(1) "("")"] SwCaseLabel (MoreSwCaseLabel)* ":" Sequence_CodeUnit_InBlock @!; SwCaseLabel: | [] ; MoreSwCaseLabel: "|" SwCaseLabel; ExternDecl: "extern" Block; PPIncludeStatement: "#" "include" JAVATOKEN(findLineEnd)@!;//"<" JAVATOKEN(findEndGT); PPDefineStatement: LL(2) "#" "define" JAVATOKEN(findLineEnd)@! | LL(2) "#" "undef" JAVATOKEN(findLineEnd)@!; PPIfDef_TopLevel: IfDefLine @+ Sequence_CodeUnit_TopLevel (LL(2) IfElseIf_TopLevel)* [ LL(2) @- "#" "else" @+! Sequence_CodeUnit_TopLevel ] @- "#" "endif" @!; PPIfDef_BlockLevel: IfDefLine @+ Sequence_CodeUnit_InBlock (LL(2) IfElseIf_BlockLevel)* [ LL(2)@- "#" "else" @+! Sequence_CodeUnit_InBlock @!] @-"#" "endif"@!; PPOtherIgnore: "line" | "pragma" |"error"; IfDefLine: LL(2) "#" "ifdef" @!| LL(2) "#" "ifndef" @! | "#" "if" JAVATOKEN(findLineEnd)@!; IfElseIf: LL(2) "#" "elif" | "#" "elsif"; IfElseIf_BlockLevel: @- IfElseIf JAVATOKEN(findLineEnd) @+! Sequence_CodeUnit_InBlock; IfElseIf_TopLevel: IfElseIf JAVATOKEN(findLineEnd)@! Sequence_CodeUnit_TopLevel; Function: FunctionHeader [FunctionParameterList] ")" @+! BlockOrSemi @-!; FunctionHeader: (Modifier)* FunctionReturnType ["*"] [LL(1) FunctionExoticStuff] "("; FunctionReturnType: ["const"] ["struct" ]["unsigned"] ; Modifier: "static" | "inline" | "__inline__" | "__inline" | "extern" | "__TIPOFUNC__"; FunctionExoticStuff: "__regbank" "(" ")"; FunctionParameterList: &LI FunctionParameter ("," &LI FunctionParameter)*; FunctionParameter: (VarDeclToken)+; Block: "{" @+! Sequence_CodeUnit_InBlock @-! "}"; GotoLabel: ":"; Sequence_CodeUnit_InBlock: (LL(2) CodeUnit_InBlock)*; BlockOrSemi: LL(1) ";" | LL(1) Block | (VarDecl)+ Block;//oldstyle method declarations BlockOrSingleStatement: LL(1) Block | CodeUnit_InBlock; TypeDef: LL(2) "typedef" "enum" (AnyTypeDefToken)* ";"@! | "typedef" (AnyStmtToken)* ";"@! ; BlockAssignment: //= {a,b} "=" [Cast] "{" JAVATOKEN(findEndCCB); EnumBlock: "enum" [] "{" JAVATOKEN(findEndCCB); Cast: "(" FunctionReturnType ")"; AnyTypeDefToken: LL(1) "{" | "}" | AnyStmtToken; AnyStmtToken: | | | "," | "|" | "<" | ">" | "(" | ")" | Block | "if" | "else" | "for" | "while" | LL(3) EnumBlock | "enum" | "*" | LL("\"=\" [Cast()]\"{\"") BlockAssignment | "=" | ":" | Modifier | "ifdef" | "ifndef" | "define" | "include" | "elif" | "elsif" | PPOtherIgnore | "const" | "struct" | "unsigned"; VarDecl: (VarDeclTokenOrComma)* ";"@!; VarDeclTokenOrComma: VarDeclToken | ","; VarDeclToken: | | "*" | | "|" | "const" | "struct" | "unsigned" | "enum" | PPOtherIgnore | Modifier | "(" JAVATOKEN(findEndCB); //TestOnly: Literal: ;