diff --git a/src/META-INF/MANIFEST.MF b/src/META-INF/MANIFEST.MF index 898640f..13c98c1 100644 --- a/src/META-INF/MANIFEST.MF +++ b/src/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: V%Bundle-Name Bundle-SymbolicName: net.sourceforge.veditor; singleton:=true -Bundle-Version: 1.2.1.11 +Bundle-Version: 1.2.1.13 Bundle-ClassPath: veditor.jar Bundle-Activator: net.sourceforge.veditor.VerilogPlugin Bundle-Vendor: %Bundle-Vendor diff --git a/src/src/net/sourceforge/veditor/parser/verilog/VerilogParserCore.jj b/src/src/net/sourceforge/veditor/parser/verilog/VerilogParserCore.jj index cbc0900..0501a25 100644 --- a/src/src/net/sourceforge/veditor/parser/verilog/VerilogParserCore.jj +++ b/src/src/net/sourceforge/veditor/parser/verilog/VerilogParserCore.jj @@ -1,1451 +1,1452 @@ -/******************************************************************************* - * Copyright (c) 2004, 2012 KOBAYASHI Tadashi and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * KOBAYASHI Tadashi - initial API and implementation - *******************************************************************************/ - -options { - JAVA_UNICODE_ESCAPE = true ; - STATIC = false ; -} - -PARSER_BEGIN(VerilogParserCore) - -package net.sourceforge.veditor.parser.verilog; - -public abstract class VerilogParserCore -{ - public static final int STATEMENT = 0; - public static final int ASSIGN_STMT = 1; - public static final int INITIAL_BLOCK = 2; - public static final int ALWAYS_BLOCK = 3; - - protected abstract void begin(int mode); - protected abstract void end(int mode); - protected abstract void beginOutlineElement(Token begin, String name, String type); - protected abstract void endOutlineElement(Token end, String name, String type); - - protected void beginOutlineElement(Token begin, String type) { - beginOutlineElement(begin, begin.image, type); - } - protected void endOutlineElement(Token end, String type) { - endOutlineElement(end, end.image, type); - } - - protected abstract void addCollapsible(int startLine,int endLine); - protected abstract Expression operator(Expression arg, Token op); - protected abstract Expression operator(Expression arg1, Token op, Expression arg2); - protected abstract Expression operator(Expression arg1, Token op, Expression arg2, Expression arg3); - protected abstract Expression variableReference(Identifier ident); - protected abstract Expression functionReference(Identifier ident); - - protected abstract void parameterAssignment(String name, Expression value); - protected abstract void variableAssignment(Identifier ident); - protected abstract void taskReference(Identifier ident); - protected abstract void variableConnection(Expression arg, String module, Identifier port); - protected abstract void variableConnection(Expression arg, String module, int portIndex); - protected abstract void evaluateAssignment(Token asn, int lvalue, Expression exp); - protected abstract void beginGenerateBlock(Identifier block); - protected abstract void endGenerateBlock(Identifier block); -} - -PARSER_END(VerilogParserCore) - -// -// operation for /* */ -// -MORE : -{ - "/*" : IN_MULTI_LINE_COMMENT -} - - -SKIP : -{ - : DEFAULT -} - - -MORE : -{ - < ~[] > -} - -// -// operation for (* *) -// -MORE : -{ - <"(*" ~[")"]> : IN_PROPERTY -} - - -SKIP : -{ - : DEFAULT -} - - -MORE : -{ - < ~[] > -} - -SKIP : -{ - " " | "\t" | "\r" | "\n" | "\f" -} - -MORE : -{ < ("//")* ("`")* (" " | "\t")* "pragma" (" " | "\t")+ "protect" (" " | "\t")+ "begin_protected" (~["\n"])*> : IN_PROTECTED -} - - -SKIP : -{ - : DEFAULT -} - - -MORE : -{ - < ~[] > -} - -SPECIAL_TOKEN : -{ - -} - -TOKEN : -{ - -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| < WIRE: "wire" > -| -| -| -| -| -| -| -| -| -| -| -| -| -| < TIME: "time" > -| < REALTIME: "realtime" > -| < DEFPARAM: "defparam" > -| < OR: "or" > -| < DISABLE: "disable" > -| -| -| < EDGE: ( "posedge" | "negedge" ) > -| < SUPPLY : ( "supply0" | "supply1" ) > -| < NET_TYPE: ( "tri" | "tri1" | "wand" | "triand" | "tri0" | "wor" | "trior" ) > -| < STRENGTH: ("strong0" | "strong1" | "pull0" | "pull1" | "weak0" | "weak1" |"highz0" | "highz1" ) > -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| < DOT: "." > -//| -} - -TOKEN : -{ - < AGN: "=" > -| < GT: ">" > -| < LT: "<" > -| < BANG: "!" > -| < TILDE: "~" > -| < HOOK: "?" > -| < COLON: ":" > -| < PCOLON: "+:" > -| < MCOLON: "-:" > -| < EQ: "==" > -| < LE: "<=" > -| < GE: ">=" > -| < NE: "!=" > -| < SC_OR: "||" > -| < SC_AND: "&&" > -| < PLUS: "+" > -| < MINUS: "-" > -| < STAR: "*" > -| < SLASH: "/" > -| < BIT_AND: "&" > -| < BIT_OR: "|" > -| < XOR: "^" > -| < REM: "%" > -| < LSHIFT: "<<" > -| < RSHIFT: ">>" > -| < NEG_AND: "~&" > -| < NEG_OR: "~|" > -| < NEG_XOR: "~^" > -| < XOR_NEG: "^~" > -| < EQ_C: "===" > -| < NE_C: "!==" > -| < POWER: "**" > -| < ALSHIFT: "<<<" > -| < ARSHIFT: ">>>" > -} - -TOKEN : -{ - < IDENT : - // No matching macro means simple identifier - ("`")? < LETTER > (< LETTER > | ["0"-"9"] )* - | < BACKSLASH > (~[ " " ])+ - > -| < SYSTEM_IDENT: - "$" < LETTER > (< LETTER > | ["0"-"9"])* - > -| < #LETTER : [ "a"-"z", "A"-"Z", "_" ] > -| < #BACKSLASH : "\\" > -} - -TOKEN : -{ - < INTEGER_LITERAL : - < NUMBER_LITERAL > - | < DECIMAL_LITERAL > - | < HEX_LITERAL > - | < OCTAL_LITERAL > - | < BINARY_LITERAL > - > -| < #NUMBER_LITERAL : ([ "0"-"9", "_" ])+ > -| < #DECIMAL_LITERAL : ([ "0"-"9" ])* "'" (["s", "S"])? [ "d", "D" ] ([" ", "\t"])* ([ "0"-"9", "_", "x", "X", "z", "Z", "?"])* > -| < #HEX_LITERAL : ([ "0"-"9" ])* "'" (["s", "S"])? [ "h", "H" ] ([" ", "\t"])* ([ "0"-"9", "a"-"f", "A"-"F", "_", "x", "X", "z", "Z", "?" ])+ > -| < #OCTAL_LITERAL : ([ "0"-"9" ])* "'" (["s", "S"])? [ "o", "O" ] ([" ", "\t"])* ([ "0"-"7", "_", "x", "X", "z", "Z", "?" ])* > -| < #BINARY_LITERAL : ([ "0"-"9" ])* "'" (["s", "S"])? [ "b", "B" ] ([" ", "\t"])* ([ "0"-"1", "_", "x", "X", "z", "Z", "?" ])* > -| < REAL_LITERAL : - ([ "0"-"9" ])+ "." ([ "0"-"9" ])* - | ([ "0"-"9" ])+ ( "." ([ "0"-"9" ])*)? [ "e", "E" ] ([ "+", "-" ])? ([ "0"-"9" ])+ > -| < STRING_LITERAL: - "\"" - ( (~["\"","\n","\r"]) - | ("\\" - ( ["n","t","b","r","f","\\","'","\""] - | ["0"-"7"] ( ["0"-"7"] )? - | ["0"-"3"] ["0"-"7"] ["0"-"7"] - ) - ) - )* - "\"" > -} - -void verilogText() : -{} -{ - ( moduleDecl() )* -} - -void moduleDecl() : -{ - Identifier name; - Token end; -} -{ - ( )* // ignore preprocessor directive - < MODULE > name = identifier() - { - beginOutlineElement(name, "module#"); - } - [ "#" "(" [ parameterArg() ( "," [] parameterArg() )* ] ")" ] - [ "(" [ argument() ( "," argument() )* ] ")" ] - ";" - ( moduleItem() )* - end = < ENDMODULE > - { - endOutlineElement(end, name. image, "module#"); - } -} - -void parameterArg() : -{ - Token name,value; - String mod, range; -} -{ - mod = parameterModifier() range = bitRange() - parameterAssign("parameter", mod, range) -} - -String parameterModifier() : -{ - String ret = " "; -} -{ - ( - ("real" | "integer" | "signed" | "time" ) - { - ret += token.image + " "; - } - )* - { - return ret; - } -} - - -void parameterAssign(String type, String mod, String range) : -{ - Identifier name; - Expression value; -} -{ - name = identifier() - "=" - value = constantExpression() - { - String types = type + "#" + mod + "#" + range + "#" + value.toString(); - beginOutlineElement(name, types); - parameterAssignment(name.image, value); - endOutlineElement(name, types); - } -} - -void argument() : -{ - Token direction; - Identifier name; - String modifier=""; - String range; - Token asn; - Expression exp; -} -{ - // C++ style argument - ( direction= | direction= | direction= ) - modifier = variableModifier() - range = bitRange() - name = identifier() - { - String types = "port#" + direction.image + "#" + modifier + "#" + range; - beginOutlineElement(name, types); - endOutlineElement(name, types); - } - [ - asn = "=" exp = expression() - { - variableAssignment(name); - evaluateAssignment(asn, name.getWidth(), exp); - } - ] - | - // C style argument, portDecl will add it to OutlineContainer - identifier() -} - -void moduleItem() : -{} -{ - moduleOrGenerateItem() -| portDecl() -| {begin(STATEMENT);} skipTo( ENDSPECIFY ) {end(STATEMENT);} -| generate() -| skipTo(ENDPROPERTY) -} - -void moduleOrGenerateItem() : -{} -{ - variableDecl() -| parameterDecl() -| taskDecl() -| functionDecl() -| {begin(STATEMENT);} skipTo( EOS ) {end(STATEMENT);} -| assign() -| primitiveInstance() -| LOOKAHEAD(3) moduleInstance() -| initialAlways() // initial and always -| skipTo(EOS) -| identifier() ":" skipTo(EOS) -| ";" -} - -void portDecl() : -{ - Token direction; - String modifier; - String range; -} -{ - ( direction= | direction= | direction= ) - modifier = variableModifier() - { begin(STATEMENT); } - range = bitRange() - portDeclSingle(direction, modifier, range) - ("," portDeclSingle(direction, modifier, range))* ";" - { end(STATEMENT); } -} - -String variableModifier() : -{ - String ret = ""; - String type = ""; -} -{ - ( - type = netType() - { - ret += type + " "; - } - | ( "real" | "realtime" | "integer" | "reg" | "signed" | "time" ) - { - ret += token.image + " "; - } - )* - { - return ret; - } -} - -void portDeclSingle(Token direction, String modifier, String range) : -{ - Identifier name; - Token asn; - Expression exp; -} -{ - name = identifier() - { - String type = "port#" + direction.image + "#" + modifier + "#" + range + "#cstyle"; - beginOutlineElement(name, type); - endOutlineElement(name, type); - } - [ - asn = "=" exp = expression() - { - variableAssignment(name); - evaluateAssignment(asn, name.getWidth(), exp); - } - ] -} - -void primitiveInstance(): -{ - String prim; -} -{ - ( | "or" - | - | - | - | - | - ) { prim = token.image;} - [ LOOKAHEAD(2) strength() ] [ delay3() ] - [ identifier() bitRange() ] "(" portConnect(prim) ")" - ( "," identifier() bitRange() "(" portConnect(prim) ")" )* - ";" -} - -void moduleInstance(): -{ - Identifier module, inst; - Token iend ; -} -{ - module = identifier() - { begin(STATEMENT); } - - ( //module instantiation - ( [ "#" ( identifier() | number() | "(" parameterConnect() ")" ) ] - inst = identifier() - { - beginOutlineElement(module, inst.image, "instance#"+module.image); - } - [ "(" [ portConnect(module.image) ] ")" ] - iend = ";" - { - endOutlineElement(iend, inst.image, "instance#"+module.image); - addCollapsible(module.beginLine, iend.endLine); - } - ) - | //user defined primitive - ( "(" portConnect(module.image) ")" - iend = ";" - ) - ) - { end(STATEMENT); } -} - -void parameterConnect() : -{} -{ - "." identifier() "(" [ constantExpression() ] ")" ( "," "." identifier() "(" [ constantExpression() ] ")" )* -| constantExpression() ( "," constantExpression() )* -} - -void portConnect(String module) : -{ - int count = 0; -} -{ - count = portConnectSingle(module, count) - ( "," count = portConnectSingle(module, count) )* -} - -int portConnectSingle(String module, int count) : -{ - Identifier port; - Expression arg = null; -} -{ - "." port = identifier() "(" [ arg = expression() ] ")" - { - variableConnection(arg, module, port); - return count + 1; - } -| arg = expression() - { - variableConnection(arg, module, count); - return count + 1; - } -} - -void assign() : -{ - int width; - Token asn; - Expression exp; -} -{ - "assign" - {begin(ASSIGN_STMT); } - [ strength() ] [ delay3() ] - width = lvalue() asn = "=" exp = expression() - { - evaluateAssignment(asn, width, exp); - } - ( - "," width = lvalue() asn = "=" exp = expression() - { - evaluateAssignment(asn, width, exp); - } - )* - ";" - {end(ASSIGN_STMT); } -} - -void variableDecl(): -{ - Token variable; - String type; - String range; -} -{ - type = variableType() - { begin(STATEMENT); } - [ strength() ] - [ "signed" { type += " signed";} ] - range = bitRange() - [ delay3() ] - variableDeclSingle(type, range) ( "," variableDeclSingle(type, range) )* ";" - { end(STATEMENT); } -} - -String variableType() : -{ - String type; -} -{ - type = netType() - { - return type; - } -| ( "reg" | "real" | "integer" | "event" |"genvar" | "time" | "realtime" ) - { - return token.image; - } -} - -void variableDeclSingle(String mod, String range) : -{ - Identifier variable; - Token asn; - Expression exp; - int dimension = 0; -} -{ - variable = identifier() - ("[" constantExpression() ":" constantExpression() "]" { dimension++; })* - { - String type = "variable#" + mod + "#" + range + "#" + dimension; - beginOutlineElement(variable, type); - endOutlineElement(variable, type); - } - [ - asn = "=" exp = expression() - { - variableAssignment(variable); - evaluateAssignment(asn, variable.getWidth(), exp); - } - ] -} - -void delay3() : -{} -{ - "#" - ( - LOOKAHEAD(3) - delayValue() - | "(" minTypMaxExpresstion() [ "," minTypMaxExpresstion() ["," minTypMaxExpresstion() ] ] ")" - ) -} - -void parameterDecl(): -{ - String type; - String mod, range; -} -{ - ( - {type = "parameter";} - | {type = "localparam";} - ) - mod = parameterModifier() - range = bitRange() - parameterAssign(type, mod, range) ( "," parameterAssign(type, mod, range) )* ";" -} - -void initialAlways(): -{ - Token start; -} -{ - ( start = | start = ) - { - if (start.image.equals("initial")) - begin(INITIAL_BLOCK); - else - begin(ALWAYS_BLOCK); - } - statement() - { - if (start.image.equals("initial")) - end(INITIAL_BLOCK); - else - end(ALWAYS_BLOCK); - addCollapsible(start.beginLine,token.endLine); - } -} - -void statement() : -{ - Token end; -} -{ - assignOrTaskEnable() -| proceduralContinuousAssignment() -| proceduralTimingControlStatement() -| ifStatement() -| caseStatement() -| whileStatement() -| forStatement() -| foreverStatement() -| repeatStatement() -| waitStatement() -| "disable" identifier() ";" -| "->" identifier() ";" -| block() -| ";" -} - -void assignOrTaskEnable() : -{ - Identifier ident; - Token asn; - Expression exp; - int width; -} -{ - ident = complexIdentifier() - ( - (asn = "=" | asn = "<=") [delayOrEventControl() ] exp = expression() ";" - { - variableAssignment(ident); - evaluateAssignment(asn, ident.getWidth(), exp); - } - | [ "(" expression() ("," expression())* ")"] ";" - { - taskReference(ident); - } - ) -| width = lvalueConcatenation() (asn = "=" | asn = "<=") [delayOrEventControl() ] exp = expression() ";" - { - evaluateAssignment(asn, width, exp); - } -| [ "(" expression() ("," expression())* ")"] ";" -} - -void delayOrEventControl() : -{} -{ - delayContol() | eventContol() -} - -void delayContol() : -{} -{ - "#" ( delayValue() | "(" minTypMaxExpresstion() ")" ) -} - -void delayValue() : -{} -{ - number() | identifier() -} - -void eventContol() : -{} -{ - "@" - ( identifier() - | "*" - | "(" (eventExpression() | "*" ) ")" - ) -} - -void eventExpression(): -{} -{ - ( expression() | < EDGE > expression() ) - ( ("," | "or") ( expression() | < EDGE > expression() ) )* - // 'repeat' '(' expression ')' event_control -> ignored -} - -void proceduralContinuousAssignment() : -{ - int width; - Token asn; - Expression exp; -} -{ - "assign" width = lvalue() asn = "=" exp = expression() ";" - { - evaluateAssignment(asn, width, exp); - } -| "deassign" lvalue() ";" -| "force" width = lvalue() asn = "=" exp = expression() ";" - { - evaluateAssignment(asn, width, exp); - } -| "release" lvalue() ";" -} - -void proceduralTimingControlStatement() : -{} -{ - delayOrEventControl() statement() -} - -void ifStatement() : -{} -{ - "(" expression() ")" statement() - [ LOOKAHEAD(1) statement() ] -} - -void caseStatement() : -{} -{ - "(" expression() ")" - ( - expression() ("," expression())* ":" statement() - | "default" [":"] statement() - )+ - -} - -void whileStatement() : -{} -{ - "(" expression() ")" statement() -} - -void forStatement() : -{} -{ - "(" - lvalue() "=" expression() ";" - expression() ";" - lvalue() "=" expression() ")" - statement() -} - -void foreverStatement() : -{} -{ - statement() -} - -void repeatStatement() : -{} -{ - "(" expression() ")" statement() -} - -void waitStatement() : -{} -{ - "(" expression() ")" statement() -} - -void block() : -{} -{ - ( | ) - [ ":" identifier() ( blockItem() )* ] - ( statement() )* - ( | ) -} - -void blockItem(): -{} -{ - parameterDecl() -| variableDecl() -} - -void functionDecl(): -{} -{ - {begin(STATEMENT);} function() {end(STATEMENT);} -} - -void taskDecl(): -{} -{ - {begin(STATEMENT);} task() {end(STATEMENT);} -} - -void function() : -{ - String range; - Identifier name; - Token end ; -} -{ - variableModifier() range = bitRange() name = identifier() - [ "(" skipTo(RPAREN) ] - ";" - { - beginOutlineElement(name, "function#" + range); - } - end = skipTo( ENDFUNCTION ) - { - endOutlineElement(end, name.image, "function#" + range); - addCollapsible(name.beginLine, end.endLine); - } -} - -void task() : -{ - Identifier name; - Token end ; -} -{ - name = identifier() ";" - { - beginOutlineElement(name, "task#"); - } - end = skipTo( ENDTASK ) - { - endOutlineElement(end, name.image, "task#"); - addCollapsible(name.beginLine, end.endLine); - } -} - -void generate() : -{} -{ - - ( generateItem() )* - -} - -void generateItem() : -{ - Identifier block = null; -} -{ - moduleOrGenerateItem() -| generateIfStatement() -| generateCaseStatement() -| generateForStatement() -| ( - [ ":" block = identifier() ] - { - if (block != null) - beginGenerateBlock(block); - } - ( generateItem() )* - - { - if (block != null) { - endGenerateBlock(block); - } - } - ) -} - -void generateIfStatement() : -{} -{ - "(" constantExpression() ")" generateItem() - [ LOOKAHEAD(1) generateItem() ] -} - -void generateCaseStatement() : -{} -{ - "(" constantExpression() ")" - ( - constantExpression() ("," constantExpression())* ":" generateItem() - | "default" ":" generateItem() - )+ - -} - -void generateForStatement() : -{} -{ - "(" - lvalue() "=" expression() ";" - expression() ";" - lvalue() "=" expression() ")" - generateItem() -} - - -String netType() : -{} -{ - ( "wire" | < NET_TYPE > | < SUPPLY > ) - { - return token.image; - } -} - -void strength() : -{} -{ - "(" ( < STRENGTH > | < SUPPLY > ) ["," ( < STRENGTH > | < SUPPLY > ) ]")" -} - -int lvalue() : -{ - int width; - Identifier ident; -} -{ - ident = complexIdentifier() - { - variableAssignment(ident); - return ident.getWidth(); - } -| width = lvalueConcatenation() - { - return width; - } -} - -int lvalueConcatenation() : -{ - int width; - int ret; -} -{ - "{" ret = lvalue() - ( "," - width = lvalue() - { - if (width == 0 || ret == 0) - ret = 0; - else - ret += width; - } - )* - "}" - { - return ret; - } -} - -Identifier identifier() : -{ - Token token; -} -{ - token = < IDENT > - { - return new Identifier(token); - } -} - -Expression constantExpression() : -{ - Expression ret; -} -{ - ret = expression() - { - return ret; - } -} - -Expression expression() : -{ - Expression ret, exp1, exp2; - Token op; -} -{ - ret = logicalOrExpresstion() - [ - op = "?" exp1 = expression() ":" exp2 = expression() - { - ret = operator(ret, op, exp1, exp2); - } - ] - { - return ret; - } -} - -Expression logicalOrExpresstion() : -{ - Expression ret, exp; - Token op; -} -{ - ret = logicalAndExpresstion() - ( op = "||" exp = logicalAndExpresstion() { ret = operator(ret, op, exp); } )* - { - return ret; - } -} - -Expression logicalAndExpresstion() : -{ - Expression ret, exp; - Token op; -} -{ - ret = bitOrExpresstion() - ( op = "&&" exp = bitOrExpresstion() { ret = operator(ret, op, exp); } )* - { - return ret; - } -} - -Expression bitOrExpresstion() : -{ - Expression ret, exp; - Token op; -} -{ - ret = bitAndExpresstion() - ( op = "|" exp = bitAndExpresstion() { ret = operator(ret, op, exp); } )* - { - return ret; - } -} - -Expression bitAndExpresstion() : -{ - Expression ret, exp; - Token op; -} -{ - ret = equalityExpression() - ( - (op = "&" | op = "^" | op = "~^" | op = "^~") - exp = equalityExpression() { ret = operator(ret, op, exp); } - )* - { - return ret; - } -} - -Expression equalityExpression() : -{ - Expression ret, exp; - Token op; -} -{ - ret = relationalExpression() - ( - (op = "==" | op = "===" | op = "!=" | op = "!==") - exp = relationalExpression() { ret = operator(ret, op, exp); } - )* - { - return ret; - } -} - -Expression relationalExpression() : -{ - Expression ret, exp; - Token op; -} -{ - ret = shiftExpression() - ( - (op = "<" | op = "<=" | op = ">" | op = ">=") - exp = shiftExpression() { ret = operator(ret, op, exp); } - )* - { - return ret; - } -} - -Expression shiftExpression() : -{ - Expression ret, exp; - Token op; -} -{ - ret = addExpression() - ( - (op = "<<" | op = ">>" | op = "<<<" | op = ">>>") - exp = addExpression() { ret = operator(ret, op, exp); } - )* - { - return ret; - } -} - -Expression addExpression() : -{ - Expression ret, exp; - Token op; -} -{ - ret = multiplyExpression() - ( - (op = "+" | op = "-" ) - exp = multiplyExpression() { ret = operator(ret, op, exp); } - )* - { - return ret; - } -} - -Expression multiplyExpression() : -{ - Expression ret, exp; - Token op; -} -{ - ret = unaryExpression() - ( - (op = "*" | op = "/" | op = "%" | op = "**") - exp = unaryExpression() { ret = operator(ret, op, exp); } - )* - { - return ret; - } -} - -Expression unaryExpression() : -{ - Expression ret, exp; - Token op = null; -} -{ - [ op = unaryOperator() ] - ret = primary() - { - if (op != null) - return operator(ret, op); - else - return ret; - } -} - -Expression primary() : -{ - Expression ret; - Identifier ident; - boolean isFunc = false; -} -{ - ( - ret = number() - | ident = complexIdentifier() [ functionArgs() {isFunc = true; }] - { - if (isFunc) { - ret = functionReference(ident); - } else { - ret = variableReference(ident); - } - } - | < SYSTEM_IDENT > ()* [ LOOKAHEAD(2) functionArgs()] - { - ret = new Expression(); - } - | ret = concatenation() - | "(" ret = minTypMaxExpresstion() ")" - ) - { - if (ret == null) - return new Expression(); - else - return ret; - } -} - -Identifier complexIdentifier() : -{ - Identifier ident, concat; -} -{ - ident = identifier() bitOrAry(ident) - ( - "." concat = identifier() bitOrAry(concat) - { - ident.endLine = concat.endLine; - ident.endColumn = concat.endColumn; - ident.image += "." + concat.image; - ident.setWidth(concat.getWidth()); - ident.setDimension(concat.getDimension()); - } - )* - { - return ident; - } -} - -Expression minTypMaxExpresstion() : -{ - Expression exp; -} -{ - exp = expression() - [ - ":" expression() - ":" expression() - ] - { - return exp; - } -} - -void bitOrAry(Identifier ident) : -{ - int width = 0; - int dim = 0; - Expression msb, lsb; - Token token; -} -{ - ( - "[" msb = expression() { width = 1; dim++; } - [ - ( token = ":" | token = "+:" | token = "-:" ) lsb = expression() - { - if (token.image.equals(":")) { - if (msb.isValid() && lsb.isValid()) - width = msb.intValue() - lsb.intValue() + 1; - else - width = 0; - } else { - if (lsb.isValid()) - width = lsb.intValue(); - else - width = 0; - } - } - ] - "]" - )* - { - ident.setWidth(width); - ident.setDimension(dim); - } -} - -String bitRange() : -{ - Expression msb, lsb; -} -{ - [ - "[" msb = expression() ":" lsb = expression() "]" - { - if (msb.isValid() && lsb.isValid()) - return "[" + msb.intValue() + ":" + lsb.intValue() + "]"; - else - return ""; - } - ] - { - return ""; - } -} - -Token unaryOperator() : -{} -{ - ( "~" | "+" | "-" | "!" | "&" | "~&" | "|" | "~|" | "^" | "~^" | "^~" ) - { - return token; - } -} - -Expression concatenation() : -{ - int width; - int value; - boolean valid; - boolean assignable; - Expression exp; - Expression refs = new Expression(); -} -{ - "{" exp = expression() - { - width = exp.getWidth(); - value = exp.intValue(); - valid = exp.isValid(); - assignable = exp.isAssignable(); - refs.addReference(exp); - } - [ - ( "," exp = expression() - { - if (width == 0 || exp.getWidth() == 0) - width = 0; - else - width += exp.getWidth(); - value = (value << width) | exp.intValue(); - valid = valid && exp.isValid(); - assignable = assignable && exp.isAssignable(); - refs.addReference(exp); - } - )+ - | "{" exp = expression() "}" - { - width = valid ? value : 0; - value = exp.intValue(); - valid = exp.isValid(); - assignable = exp.isAssignable(); - refs = exp; - } - ] - "}" - { - Expression ret = new Expression(width); - if (valid) - ret.setValue(value); - ret.setAssignable(assignable); - ret.addReference(refs); - return ret; - } -} - -void functionArgs(): -{} -{ - "(" expression() ( "," expression() )* ")" -} - -Expression number() : -{ - Expression ret = new Expression(); -} -{ - ( - < INTEGER_LITERAL > { ret.parseIntegerLiteral(token.image); } - | < REAL_LITERAL > { ret.parseRealLiteral(token.image); } - | < STRING_LITERAL > { ret.parseStringLiteral(token.image); } - ) - { - return ret; - } -} - - -JAVACODE -void unexpectedEof(Token token) -{ - ParseException ex = new ParseException("unexpected EOF"); - ex.currentToken = token; - throw ex; -} - -JAVACODE -Token skipTo(int skip) -{ - Token current = token; - Token token ; - StringBuffer image = new StringBuffer(); - - for(;;) - { - token = getToken(1); - if (token.kind == EOF) - unexpectedEof(current); - if (token.kind == skip) - { - getNextToken(); - break ; - } - - image.append(token.image); - getNextToken(); - } - token.image = image.toString(); - return token ; -} - +/******************************************************************************* + * Copyright (c) 2004, 2012 KOBAYASHI Tadashi and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * KOBAYASHI Tadashi - initial API and implementation + *******************************************************************************/ + +options { + JAVA_UNICODE_ESCAPE = true ; + STATIC = false ; +} + +PARSER_BEGIN(VerilogParserCore) + +package net.sourceforge.veditor.parser.verilog; + +public abstract class VerilogParserCore +{ + public static final int STATEMENT = 0; + public static final int ASSIGN_STMT = 1; + public static final int INITIAL_BLOCK = 2; + public static final int ALWAYS_BLOCK = 3; + + protected abstract void begin(int mode); + protected abstract void end(int mode); + protected abstract void beginOutlineElement(Token begin, String name, String type); + protected abstract void endOutlineElement(Token end, String name, String type); + + protected void beginOutlineElement(Token begin, String type) { + beginOutlineElement(begin, begin.image, type); + } + protected void endOutlineElement(Token end, String type) { + endOutlineElement(end, end.image, type); + } + + protected abstract void addCollapsible(int startLine,int endLine); + protected abstract Expression operator(Expression arg, Token op); + protected abstract Expression operator(Expression arg1, Token op, Expression arg2); + protected abstract Expression operator(Expression arg1, Token op, Expression arg2, Expression arg3); + protected abstract Expression variableReference(Identifier ident); + protected abstract Expression functionReference(Identifier ident); + + protected abstract void parameterAssignment(String name, Expression value); + protected abstract void variableAssignment(Identifier ident); + protected abstract void taskReference(Identifier ident); + protected abstract void variableConnection(Expression arg, String module, Identifier port); + protected abstract void variableConnection(Expression arg, String module, int portIndex); + protected abstract void evaluateAssignment(Token asn, int lvalue, Expression exp); + protected abstract void beginGenerateBlock(Identifier block); + protected abstract void endGenerateBlock(Identifier block); +} + +PARSER_END(VerilogParserCore) + +// +// operation for /* */ +// +MORE : +{ + "/*" : IN_MULTI_LINE_COMMENT +} + + +SKIP : +{ + : DEFAULT +} + + +MORE : +{ + < ~[] > +} + +// +// operation for (* *) +// +MORE : +{ + <"(*" ~[")"]> : IN_PROPERTY +} + + +SKIP : +{ + : DEFAULT +} + + +MORE : +{ + < ~[] > +} + +SKIP : +{ + " " | "\t" | "\r" | "\n" | "\f" +} + +MORE : +{ + < ("//")* ("`")* (" " | "\t")* "pragma" (" " | "\t")+ "protect" (" " | "\t")+ "begin_protected" (~["\n"])*> : IN_PROTECTED +} + + +SKIP : +{ + : DEFAULT +} + + +MORE : +{ + < ~[] > +} + +SPECIAL_TOKEN : +{ + +} + +TOKEN : +{ + +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| < WIRE: "wire" > +| +| +| +| +| +| +| +| +| +| +| +| +| +| < TIME: "time" > +| < REALTIME: "realtime" > +| < DEFPARAM: "defparam" > +| < OR: "or" > +| < DISABLE: "disable" > +| +| +| < EDGE: ( "posedge" | "negedge" ) > +| < SUPPLY : ( "supply0" | "supply1" ) > +| < NET_TYPE: ( "tri" | "tri1" | "wand" | "triand" | "tri0" | "wor" | "trior" ) > +| < STRENGTH: ("strong0" | "strong1" | "pull0" | "pull1" | "weak0" | "weak1" |"highz0" | "highz1" ) > +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| < DOT: "." > +//| +} + +TOKEN : +{ + < AGN: "=" > +| < GT: ">" > +| < LT: "<" > +| < BANG: "!" > +| < TILDE: "~" > +| < HOOK: "?" > +| < COLON: ":" > +| < PCOLON: "+:" > +| < MCOLON: "-:" > +| < EQ: "==" > +| < LE: "<=" > +| < GE: ">=" > +| < NE: "!=" > +| < SC_OR: "||" > +| < SC_AND: "&&" > +| < PLUS: "+" > +| < MINUS: "-" > +| < STAR: "*" > +| < SLASH: "/" > +| < BIT_AND: "&" > +| < BIT_OR: "|" > +| < XOR: "^" > +| < REM: "%" > +| < LSHIFT: "<<" > +| < RSHIFT: ">>" > +| < NEG_AND: "~&" > +| < NEG_OR: "~|" > +| < NEG_XOR: "~^" > +| < XOR_NEG: "^~" > +| < EQ_C: "===" > +| < NE_C: "!==" > +| < POWER: "**" > +| < ALSHIFT: "<<<" > +| < ARSHIFT: ">>>" > +} + +TOKEN : +{ + < IDENT : + // No matching macro means simple identifier + ("`")? < LETTER > (< LETTER > | ["0"-"9"] )* + | < BACKSLASH > (~[ " " ])+ + > +| < SYSTEM_IDENT: + "$" < LETTER > (< LETTER > | ["0"-"9"])* + > +| < #LETTER : [ "a"-"z", "A"-"Z", "_" ] > +| < #BACKSLASH : "\\" > +} + +TOKEN : +{ + < INTEGER_LITERAL : + < NUMBER_LITERAL > + | < DECIMAL_LITERAL > + | < HEX_LITERAL > + | < OCTAL_LITERAL > + | < BINARY_LITERAL > + > +| < #NUMBER_LITERAL : ([ "0"-"9", "_" ])+ > +| < #DECIMAL_LITERAL : ([ "0"-"9" ])* "'" (["s", "S"])? [ "d", "D" ] ([" ", "\t"])* ([ "0"-"9", "_", "x", "X", "z", "Z", "?"])* > +| < #HEX_LITERAL : ([ "0"-"9" ])* "'" (["s", "S"])? [ "h", "H" ] ([" ", "\t"])* ([ "0"-"9", "a"-"f", "A"-"F", "_", "x", "X", "z", "Z", "?" ])+ > +| < #OCTAL_LITERAL : ([ "0"-"9" ])* "'" (["s", "S"])? [ "o", "O" ] ([" ", "\t"])* ([ "0"-"7", "_", "x", "X", "z", "Z", "?" ])* > +| < #BINARY_LITERAL : ([ "0"-"9" ])* "'" (["s", "S"])? [ "b", "B" ] ([" ", "\t"])* ([ "0"-"1", "_", "x", "X", "z", "Z", "?" ])* > +| < REAL_LITERAL : + ([ "0"-"9" ])+ "." ([ "0"-"9" ])* + | ([ "0"-"9" ])+ ( "." ([ "0"-"9" ])*)? [ "e", "E" ] ([ "+", "-" ])? ([ "0"-"9" ])+ > +| < STRING_LITERAL: + "\"" + ( (~["\"","\n","\r"]) + | ("\\" + ( ["n","t","b","r","f","\\","'","\""] + | ["0"-"7"] ( ["0"-"7"] )? + | ["0"-"3"] ["0"-"7"] ["0"-"7"] + ) + ) + )* + "\"" > +} + +void verilogText() : +{} +{ + ( moduleDecl() )* +} + +void moduleDecl() : +{ + Identifier name; + Token end; +} +{ + ( )* // ignore preprocessor directive + < MODULE > name = identifier() + { + beginOutlineElement(name, "module#"); + } + [ "#" "(" [ parameterArg() ( "," [] parameterArg() )* ] ")" ] + [ "(" [ argument() ( "," argument() )* ] ")" ] + ";" + ( moduleItem() )* + end = < ENDMODULE > + { + endOutlineElement(end, name. image, "module#"); + } +} + +void parameterArg() : +{ + Token name,value; + String mod, range; +} +{ + mod = parameterModifier() range = bitRange() + parameterAssign("parameter", mod, range) +} + +String parameterModifier() : +{ + String ret = " "; +} +{ + ( + ("real" | "integer" | "signed" | "time" ) + { + ret += token.image + " "; + } + )* + { + return ret; + } +} + + +void parameterAssign(String type, String mod, String range) : +{ + Identifier name; + Expression value; +} +{ + name = identifier() + "=" + value = constantExpression() + { + String types = type + "#" + mod + "#" + range + "#" + value.toString(); + beginOutlineElement(name, types); + parameterAssignment(name.image, value); + endOutlineElement(name, types); + } +} + +void argument() : +{ + Token direction; + Identifier name; + String modifier=""; + String range; + Token asn; + Expression exp; +} +{ + // C++ style argument + ( direction= | direction= | direction= ) + modifier = variableModifier() + range = bitRange() + name = identifier() + { + String types = "port#" + direction.image + "#" + modifier + "#" + range; + beginOutlineElement(name, types); + endOutlineElement(name, types); + } + [ + asn = "=" exp = expression() + { + variableAssignment(name); + evaluateAssignment(asn, name.getWidth(), exp); + } + ] + | + // C style argument, portDecl will add it to OutlineContainer + identifier() +} + +void moduleItem() : +{} +{ + moduleOrGenerateItem() +| portDecl() +| {begin(STATEMENT);} skipTo( ENDSPECIFY ) {end(STATEMENT);} +| generate() +| skipTo(ENDPROPERTY) +} + +void moduleOrGenerateItem() : +{} +{ + variableDecl() +| parameterDecl() +| taskDecl() +| functionDecl() +| {begin(STATEMENT);} skipTo( EOS ) {end(STATEMENT);} +| assign() +| primitiveInstance() +| LOOKAHEAD(3) moduleInstance() +| initialAlways() // initial and always +| skipTo(EOS) +| identifier() ":" skipTo(EOS) +| ";" +} + +void portDecl() : +{ + Token direction; + String modifier; + String range; +} +{ + ( direction= | direction= | direction= ) + modifier = variableModifier() + { begin(STATEMENT); } + range = bitRange() + portDeclSingle(direction, modifier, range) + ("," portDeclSingle(direction, modifier, range))* ";" + { end(STATEMENT); } +} + +String variableModifier() : +{ + String ret = ""; + String type = ""; +} +{ + ( + type = netType() + { + ret += type + " "; + } + | ( "real" | "realtime" | "integer" | "reg" | "signed" | "time" ) + { + ret += token.image + " "; + } + )* + { + return ret; + } +} + +void portDeclSingle(Token direction, String modifier, String range) : +{ + Identifier name; + Token asn; + Expression exp; +} +{ + name = identifier() + { + String type = "port#" + direction.image + "#" + modifier + "#" + range + "#cstyle"; + beginOutlineElement(name, type); + endOutlineElement(name, type); + } + [ + asn = "=" exp = expression() + { + variableAssignment(name); + evaluateAssignment(asn, name.getWidth(), exp); + } + ] +} + +void primitiveInstance(): +{ + String prim; +} +{ + ( | "or" + | + | + | + | + | + ) { prim = token.image;} + [ LOOKAHEAD(2) strength() ] [ delay3() ] + [ identifier() bitRange() ] "(" portConnect(prim) ")" + ( "," identifier() bitRange() "(" portConnect(prim) ")" )* + ";" +} + +void moduleInstance(): +{ + Identifier module, inst; + Token iend ; +} +{ + module = identifier() + { begin(STATEMENT); } + + ( //module instantiation + ( [ "#" ( identifier() | number() | "(" parameterConnect() ")" ) ] + inst = identifier() + { + beginOutlineElement(module, inst.image, "instance#"+module.image); + } + [ "(" [ portConnect(module.image) ] ")" ] + iend = ";" + { + endOutlineElement(iend, inst.image, "instance#"+module.image); + addCollapsible(module.beginLine, iend.endLine); + } + ) + | //user defined primitive + ( "(" portConnect(module.image) ")" + iend = ";" + ) + ) + { end(STATEMENT); } +} + +void parameterConnect() : +{} +{ + "." identifier() "(" [ constantExpression() ] ")" ( "," "." identifier() "(" [ constantExpression() ] ")" )* +| constantExpression() ( "," constantExpression() )* +} + +void portConnect(String module) : +{ + int count = 0; +} +{ + count = portConnectSingle(module, count) + ( "," count = portConnectSingle(module, count) )* +} + +int portConnectSingle(String module, int count) : +{ + Identifier port; + Expression arg = null; +} +{ + "." port = identifier() "(" [ arg = expression() ] ")" + { + variableConnection(arg, module, port); + return count + 1; + } +| arg = expression() + { + variableConnection(arg, module, count); + return count + 1; + } +} + +void assign() : +{ + int width; + Token asn; + Expression exp; +} +{ + "assign" + {begin(ASSIGN_STMT); } + [ strength() ] [ delay3() ] + width = lvalue() asn = "=" exp = expression() + { + evaluateAssignment(asn, width, exp); + } + ( + "," width = lvalue() asn = "=" exp = expression() + { + evaluateAssignment(asn, width, exp); + } + )* + ";" + {end(ASSIGN_STMT); } +} + +void variableDecl(): +{ + Token variable; + String type; + String range; +} +{ + type = variableType() + { begin(STATEMENT); } + [ strength() ] + [ "signed" { type += " signed";} ] + range = bitRange() + [ delay3() ] + variableDeclSingle(type, range) ( "," variableDeclSingle(type, range) )* ";" + { end(STATEMENT); } +} + +String variableType() : +{ + String type; +} +{ + type = netType() + { + return type; + } +| ( "reg" | "real" | "integer" | "event" |"genvar" | "time" | "realtime" ) + { + return token.image; + } +} + +void variableDeclSingle(String mod, String range) : +{ + Identifier variable; + Token asn; + Expression exp; + int dimension = 0; +} +{ + variable = identifier() + ("[" constantExpression() ":" constantExpression() "]" { dimension++; })* + { + String type = "variable#" + mod + "#" + range + "#" + dimension; + beginOutlineElement(variable, type); + endOutlineElement(variable, type); + } + [ + asn = "=" exp = expression() + { + variableAssignment(variable); + evaluateAssignment(asn, variable.getWidth(), exp); + } + ] +} + +void delay3() : +{} +{ + "#" + ( + LOOKAHEAD(3) + delayValue() + | "(" minTypMaxExpresstion() [ "," minTypMaxExpresstion() ["," minTypMaxExpresstion() ] ] ")" + ) +} + +void parameterDecl(): +{ + String type; + String mod, range; +} +{ + ( + {type = "parameter";} + | {type = "localparam";} + ) + mod = parameterModifier() + range = bitRange() + parameterAssign(type, mod, range) ( "," parameterAssign(type, mod, range) )* ";" +} + +void initialAlways(): +{ + Token start; +} +{ + ( start = | start = ) + { + if (start.image.equals("initial")) + begin(INITIAL_BLOCK); + else + begin(ALWAYS_BLOCK); + } + statement() + { + if (start.image.equals("initial")) + end(INITIAL_BLOCK); + else + end(ALWAYS_BLOCK); + addCollapsible(start.beginLine,token.endLine); + } +} + +void statement() : +{ + Token end; +} +{ + assignOrTaskEnable() +| proceduralContinuousAssignment() +| proceduralTimingControlStatement() +| ifStatement() +| caseStatement() +| whileStatement() +| forStatement() +| foreverStatement() +| repeatStatement() +| waitStatement() +| "disable" identifier() ";" +| "->" identifier() ";" +| block() +| ";" +} + +void assignOrTaskEnable() : +{ + Identifier ident; + Token asn; + Expression exp; + int width; +} +{ + ident = complexIdentifier() + ( + (asn = "=" | asn = "<=") [delayOrEventControl() ] exp = expression() ";" + { + variableAssignment(ident); + evaluateAssignment(asn, ident.getWidth(), exp); + } + | [ "(" expression() ("," expression())* ")"] ";" + { + taskReference(ident); + } + ) +| width = lvalueConcatenation() (asn = "=" | asn = "<=") [delayOrEventControl() ] exp = expression() ";" + { + evaluateAssignment(asn, width, exp); + } +| [ "(" expression() ("," expression())* ")"] ";" +} + +void delayOrEventControl() : +{} +{ + delayContol() | eventContol() +} + +void delayContol() : +{} +{ + "#" ( delayValue() | "(" minTypMaxExpresstion() ")" ) +} + +void delayValue() : +{} +{ + number() | identifier() +} + +void eventContol() : +{} +{ + "@" + ( identifier() + | "*" + | "(" (eventExpression() | "*" ) ")" + ) +} + +void eventExpression(): +{} +{ + ( expression() | < EDGE > expression() ) + ( ("," | "or") ( expression() | < EDGE > expression() ) )* + // 'repeat' '(' expression ')' event_control -> ignored +} + +void proceduralContinuousAssignment() : +{ + int width; + Token asn; + Expression exp; +} +{ + "assign" width = lvalue() asn = "=" exp = expression() ";" + { + evaluateAssignment(asn, width, exp); + } +| "deassign" lvalue() ";" +| "force" width = lvalue() asn = "=" exp = expression() ";" + { + evaluateAssignment(asn, width, exp); + } +| "release" lvalue() ";" +} + +void proceduralTimingControlStatement() : +{} +{ + delayOrEventControl() statement() +} + +void ifStatement() : +{} +{ + "(" expression() ")" statement() + [ LOOKAHEAD(1) statement() ] +} + +void caseStatement() : +{} +{ + "(" expression() ")" + ( + expression() ("," expression())* ":" statement() + | "default" [":"] statement() + )+ + +} + +void whileStatement() : +{} +{ + "(" expression() ")" statement() +} + +void forStatement() : +{} +{ + "(" + lvalue() "=" expression() ";" + expression() ";" + lvalue() "=" expression() ")" + statement() +} + +void foreverStatement() : +{} +{ + statement() +} + +void repeatStatement() : +{} +{ + "(" expression() ")" statement() +} + +void waitStatement() : +{} +{ + "(" expression() ")" statement() +} + +void block() : +{} +{ + ( | ) + [ ":" identifier() ( blockItem() )* ] + ( statement() )* + ( | ) +} + +void blockItem(): +{} +{ + parameterDecl() +| variableDecl() +} + +void functionDecl(): +{} +{ + {begin(STATEMENT);} function() {end(STATEMENT);} +} + +void taskDecl(): +{} +{ + {begin(STATEMENT);} task() {end(STATEMENT);} +} + +void function() : +{ + String range; + Identifier name; + Token end ; +} +{ + variableModifier() range = bitRange() name = identifier() + [ "(" skipTo(RPAREN) ] + ";" + { + beginOutlineElement(name, "function#" + range); + } + end = skipTo( ENDFUNCTION ) + { + endOutlineElement(end, name.image, "function#" + range); + addCollapsible(name.beginLine, end.endLine); + } +} + +void task() : +{ + Identifier name; + Token end ; +} +{ + name = identifier() ";" + { + beginOutlineElement(name, "task#"); + } + end = skipTo( ENDTASK ) + { + endOutlineElement(end, name.image, "task#"); + addCollapsible(name.beginLine, end.endLine); + } +} + +void generate() : +{} +{ + + ( generateItem() )* + +} + +void generateItem() : +{ + Identifier block = null; +} +{ + moduleOrGenerateItem() +| generateIfStatement() +| generateCaseStatement() +| generateForStatement() +| ( + [ ":" block = identifier() ] + { + if (block != null) + beginGenerateBlock(block); + } + ( generateItem() )* + + { + if (block != null) { + endGenerateBlock(block); + } + } + ) +} + +void generateIfStatement() : +{} +{ + "(" constantExpression() ")" generateItem() + [ LOOKAHEAD(1) generateItem() ] +} + +void generateCaseStatement() : +{} +{ + "(" constantExpression() ")" + ( + constantExpression() ("," constantExpression())* ":" generateItem() + | "default" ":" generateItem() + )+ + +} + +void generateForStatement() : +{} +{ + "(" + lvalue() "=" expression() ";" + expression() ";" + lvalue() "=" expression() ")" + generateItem() +} + + +String netType() : +{} +{ + ( "wire" | < NET_TYPE > | < SUPPLY > ) + { + return token.image; + } +} + +void strength() : +{} +{ + "(" ( < STRENGTH > | < SUPPLY > ) ["," ( < STRENGTH > | < SUPPLY > ) ]")" +} + +int lvalue() : +{ + int width; + Identifier ident; +} +{ + ident = complexIdentifier() + { + variableAssignment(ident); + return ident.getWidth(); + } +| width = lvalueConcatenation() + { + return width; + } +} + +int lvalueConcatenation() : +{ + int width; + int ret; +} +{ + "{" ret = lvalue() + ( "," + width = lvalue() + { + if (width == 0 || ret == 0) + ret = 0; + else + ret += width; + } + )* + "}" + { + return ret; + } +} + +Identifier identifier() : +{ + Token token; +} +{ + token = < IDENT > + { + return new Identifier(token); + } +} + +Expression constantExpression() : +{ + Expression ret; +} +{ + ret = expression() + { + return ret; + } +} + +Expression expression() : +{ + Expression ret, exp1, exp2; + Token op; +} +{ + ret = logicalOrExpresstion() + [ + op = "?" exp1 = expression() ":" exp2 = expression() + { + ret = operator(ret, op, exp1, exp2); + } + ] + { + return ret; + } +} + +Expression logicalOrExpresstion() : +{ + Expression ret, exp; + Token op; +} +{ + ret = logicalAndExpresstion() + ( op = "||" exp = logicalAndExpresstion() { ret = operator(ret, op, exp); } )* + { + return ret; + } +} + +Expression logicalAndExpresstion() : +{ + Expression ret, exp; + Token op; +} +{ + ret = bitOrExpresstion() + ( op = "&&" exp = bitOrExpresstion() { ret = operator(ret, op, exp); } )* + { + return ret; + } +} + +Expression bitOrExpresstion() : +{ + Expression ret, exp; + Token op; +} +{ + ret = bitAndExpresstion() + ( op = "|" exp = bitAndExpresstion() { ret = operator(ret, op, exp); } )* + { + return ret; + } +} + +Expression bitAndExpresstion() : +{ + Expression ret, exp; + Token op; +} +{ + ret = equalityExpression() + ( + (op = "&" | op = "^" | op = "~^" | op = "^~") + exp = equalityExpression() { ret = operator(ret, op, exp); } + )* + { + return ret; + } +} + +Expression equalityExpression() : +{ + Expression ret, exp; + Token op; +} +{ + ret = relationalExpression() + ( + (op = "==" | op = "===" | op = "!=" | op = "!==") + exp = relationalExpression() { ret = operator(ret, op, exp); } + )* + { + return ret; + } +} + +Expression relationalExpression() : +{ + Expression ret, exp; + Token op; +} +{ + ret = shiftExpression() + ( + (op = "<" | op = "<=" | op = ">" | op = ">=") + exp = shiftExpression() { ret = operator(ret, op, exp); } + )* + { + return ret; + } +} + +Expression shiftExpression() : +{ + Expression ret, exp; + Token op; +} +{ + ret = addExpression() + ( + (op = "<<" | op = ">>" | op = "<<<" | op = ">>>") + exp = addExpression() { ret = operator(ret, op, exp); } + )* + { + return ret; + } +} + +Expression addExpression() : +{ + Expression ret, exp; + Token op; +} +{ + ret = multiplyExpression() + ( + (op = "+" | op = "-" ) + exp = multiplyExpression() { ret = operator(ret, op, exp); } + )* + { + return ret; + } +} + +Expression multiplyExpression() : +{ + Expression ret, exp; + Token op; +} +{ + ret = unaryExpression() + ( + (op = "*" | op = "/" | op = "%" | op = "**") + exp = unaryExpression() { ret = operator(ret, op, exp); } + )* + { + return ret; + } +} + +Expression unaryExpression() : +{ + Expression ret, exp; + Token op = null; +} +{ + [ op = unaryOperator() ] + ret = primary() + { + if (op != null) + return operator(ret, op); + else + return ret; + } +} + +Expression primary() : +{ + Expression ret; + Identifier ident; + boolean isFunc = false; +} +{ + ( + ret = number() + | ident = complexIdentifier() [ functionArgs() {isFunc = true; }] + { + if (isFunc) { + ret = functionReference(ident); + } else { + ret = variableReference(ident); + } + } + | < SYSTEM_IDENT > ()* [ LOOKAHEAD(2) functionArgs()] + { + ret = new Expression(); + } + | ret = concatenation() + | "(" ret = minTypMaxExpresstion() ")" + ) + { + if (ret == null) + return new Expression(); + else + return ret; + } +} + +Identifier complexIdentifier() : +{ + Identifier ident, concat; +} +{ + ident = identifier() bitOrAry(ident) + ( + "." concat = identifier() bitOrAry(concat) + { + ident.endLine = concat.endLine; + ident.endColumn = concat.endColumn; + ident.image += "." + concat.image; + ident.setWidth(concat.getWidth()); + ident.setDimension(concat.getDimension()); + } + )* + { + return ident; + } +} + +Expression minTypMaxExpresstion() : +{ + Expression exp; +} +{ + exp = expression() + [ + ":" expression() + ":" expression() + ] + { + return exp; + } +} + +void bitOrAry(Identifier ident) : +{ + int width = 0; + int dim = 0; + Expression msb, lsb; + Token token; +} +{ + ( + "[" msb = expression() { width = 1; dim++; } + [ + ( token = ":" | token = "+:" | token = "-:" ) lsb = expression() + { + if (token.image.equals(":")) { + if (msb.isValid() && lsb.isValid()) + width = msb.intValue() - lsb.intValue() + 1; + else + width = 0; + } else { + if (lsb.isValid()) + width = lsb.intValue(); + else + width = 0; + } + } + ] + "]" + )* + { + ident.setWidth(width); + ident.setDimension(dim); + } +} + +String bitRange() : +{ + Expression msb, lsb; +} +{ + [ + "[" msb = expression() ":" lsb = expression() "]" + { + if (msb.isValid() && lsb.isValid()) + return "[" + msb.intValue() + ":" + lsb.intValue() + "]"; + else + return ""; + } + ] + { + return ""; + } +} + +Token unaryOperator() : +{} +{ + ( "~" | "+" | "-" | "!" | "&" | "~&" | "|" | "~|" | "^" | "~^" | "^~" ) + { + return token; + } +} + +Expression concatenation() : +{ + int width; + int value; + boolean valid; + boolean assignable; + Expression exp; + Expression refs = new Expression(); +} +{ + "{" exp = expression() + { + width = exp.getWidth(); + value = exp.intValue(); + valid = exp.isValid(); + assignable = exp.isAssignable(); + refs.addReference(exp); + } + [ + ( "," exp = expression() + { + if (width == 0 || exp.getWidth() == 0) + width = 0; + else + width += exp.getWidth(); + value = (value << width) | exp.intValue(); + valid = valid && exp.isValid(); + assignable = assignable && exp.isAssignable(); + refs.addReference(exp); + } + )+ + | "{" exp = expression() "}" + { + width = valid ? value : 0; + value = exp.intValue(); + valid = exp.isValid(); + assignable = exp.isAssignable(); + refs = exp; + } + ] + "}" + { + Expression ret = new Expression(width); + if (valid) + ret.setValue(value); + ret.setAssignable(assignable); + ret.addReference(refs); + return ret; + } +} + +void functionArgs(): +{} +{ + "(" expression() ( "," expression() )* ")" +} + +Expression number() : +{ + Expression ret = new Expression(); +} +{ + ( + < INTEGER_LITERAL > { ret.parseIntegerLiteral(token.image); } + | < REAL_LITERAL > { ret.parseRealLiteral(token.image); } + | < STRING_LITERAL > { ret.parseStringLiteral(token.image); } + ) + { + return ret; + } +} + + +JAVACODE +void unexpectedEof(Token token) +{ + ParseException ex = new ParseException("unexpected EOF"); + ex.currentToken = token; + throw ex; +} + +JAVACODE +Token skipTo(int skip) +{ + Token current = token; + Token token ; + StringBuffer image = new StringBuffer(); + + for(;;) + { + token = getToken(1); + if (token.kind == EOF) + unexpectedEof(current); + if (token.kind == skip) + { + getNextToken(); + break ; + } + + image.append(token.image); + getNextToken(); + } + token.image = image.toString(); + return token ; +} + diff --git a/src/src/net/sourceforge/veditor/parser/verilog/VerilogParserReader.java b/src/src/net/sourceforge/veditor/parser/verilog/VerilogParserReader.java index d0eb6eb..01b6903 100644 --- a/src/src/net/sourceforge/veditor/parser/verilog/VerilogParserReader.java +++ b/src/src/net/sourceforge/veditor/parser/verilog/VerilogParserReader.java @@ -1,374 +1,410 @@ -/******************************************************************************* - * Copyright (c) 2012 VEditor Team - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * KOBAYASHI Tadashi - initial API and implementation - *******************************************************************************/ -package net.sourceforge.veditor.parser.verilog; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; -import java.util.HashMap; -import java.util.Map; - -import org.eclipse.core.resources.IFile; - -import net.sourceforge.veditor.parser.ParserReader; - -public class VerilogParserReader extends ParserReader { - private final static int CONTINUED = 0; - private final static int ELSE = 1; - private final static int ELSIF = 2; - private final static int ENDIF = 3; - - private CharReader reader; - private File directory; - private StringBuilder buffer; - private Map defines; - private boolean isInclude; - - public VerilogParserReader(InputStream in, IFile file) { - reader = new CharReader(new InputStreamReader(in)); - process(file); - reader.close(); - // System.out.println(buffer); - initialize(buffer.toString()); - } - - public VerilogParserReader(String text, IFile file) { - reader = new CharReader(new StringReader(text)); - process(file); - reader.close(); - // System.out.println(buffer); - initialize(buffer.toString()); - } - - private void process(IFile file) { - directory = file.getLocation().removeLastSegments(1).toFile(); - buffer = new StringBuilder(); - defines = new HashMap(); - isInclude = false; - - for (;;) { - if (reader.isEof()) - break; - // Normally it runs just once. It allows accidental `else or `endif - parseRegion(true); - } - } - - private static final int CODE = 0; - private static final int BLOCK_COMMENT = 1; - private static final int LINE_COMMENT = 2; - private static final int STRING = 3; - - private int parseRegion(boolean enable) { - int context = CODE; - - for (;;) { - if (reader.isEof()) { - return CONTINUED; - } - - char c = reader.read(); - char next; - switch (c) { - case '\n': - if (context == LINE_COMMENT) { - context = CODE; - } - break; - case '"': - if (context == CODE) { - context = STRING; - } else if (context == STRING) { - context = CODE; - } - break; - case '/': - next = reader.read(); - if (next == '/' && context == CODE) { - context = LINE_COMMENT; - reader.pushBack(next); // we push line comments through - } else if (next == '*' && context == CODE) - context = BLOCK_COMMENT; - else - reader.pushBack(next); - break; - case '*': - next = reader.read(); - if (next == '/' && context == BLOCK_COMMENT) { - context = CODE; - c = ' '; - } else { - reader.pushBack(next); - } - break; - } - if (c == '`' && context == CODE) { - int status = directive(enable); - if (status != CONTINUED) { - // if get `else `endif, return - return status; - } - } else { - if (c == '\n') { - if (isInclude) - buffer.append(' '); // for keeping line number - else - buffer.append('\n'); - } else if (enable && context != BLOCK_COMMENT) { - // do parse line comments, but skip block comments, to find pragma's - buffer.append(c); - } - } - } - } - - private int directive(boolean enable) { - String cmd = getIdent(); - - if (cmd.equals("timescale") || cmd.equals("default_nettype")) { - getToEndOfLine(); - } else if (cmd.equals("define")) { - String def = getNextIdent(); - int line = reader.getLine(); - skipSpace(); - String value; - if (line == reader.getLine()) { - value = getToEndOfLine(); - int idx = value.indexOf("//"); - if (idx >= 0) - value = value.substring(0, idx); - } else { - value = ""; - } - if (enable) - defines.put(def, value); - } else if (cmd.equals("undef")) { - String def = getNextIdent(); - if (enable) - defines.remove(def); - } else if (cmd.equals("ifdef")) { - directiveIf(enable, true); - } else if (cmd.equals("ifndef")) { - directiveIf(enable, false); - } else if (cmd.equals("else")) { - return ELSE; - } else if (cmd.equals("elsif")) { - // parse next word on upper level - return ELSIF; - } else if (cmd.equals("endif")) { - return ENDIF; - } else if (cmd.equals("include")) { - String filename = getNextString(); - // System.out.println("include:" + filename); - directiveInclude(enable, filename); - } else { - // macro replace - if (enable) { - String value = defines.get(cmd); - if (value != null) { - buffer.append(value); - } else { - // not match - buffer.append('`'); - buffer.append(cmd); - } - } - return CONTINUED; - } - return CONTINUED; - } - - private void directiveIf(boolean enable, boolean ifdef) { - String def = getNextIdent(); - boolean cond; - if (ifdef) - cond = (defines.get(def) != null); - else - cond = (defines.get(def) == null); - int status = parseRegion(enable && cond); - boolean done = cond; - while (status == ELSIF) { - def = getNextIdent(); - cond = (defines.get(def) != null); - status = parseRegion(enable && done == false && cond); - done = done || cond; - } - if (status == ELSE) { - parseRegion(enable && done == false); - } - } - - private void directiveInclude(boolean enable, String filename) { - if (enable == false) - return; - boolean storeIsInclude = isInclude; - CharReader storeReader = reader; - isInclude = true; - File file = new File(directory, filename); - try { - FileInputStream in = new FileInputStream(file); - reader = new CharReader(new InputStreamReader(in)); - parseRegion(true); - reader.close(); - } catch (IOException e) { - } - isInclude = storeIsInclude; - reader = storeReader; - } - - private String getIdent() { - StringBuffer word = new StringBuffer(); - char next = reader.read(); - while (Character.isJavaIdentifierPart(next)) { - word.append(next); - next = reader.read(); - } - reader.pushBack(next); - return word.toString(); - } - - private String getNextIdent() { - skipSpace(); - return getIdent(); - } - - private String getNextString() { - skipSpace(); - char next = reader.read(); - if (next != '"') - return ""; - StringBuffer word = new StringBuffer(); - next = reader.read(); - while (next != '"' && reader.isEof() == false) { - word.append(next); - next = reader.read(); - } - // consume last '"' - return word.toString(); - } - - private void skipSpace() { - char next = reader.read(); - while (Character.isWhitespace(next)) { - if (reader.isEof()) - return; - if (next == '\n' && isInclude == false) { - buffer.append('\n'); // for keeping line number - } - next = reader.read(); - } - reader.pushBack(next); - } - - private String getToEndOfLine() { - StringBuffer str = new StringBuffer(); - char next = reader.read(); - while (next != '\n' && reader.isEof() == false) { - str.append(next); - next = reader.read(); - } - if (isInclude == false) - buffer.append('\n'); // for keeping line number - return str.toString(); - } - - private static class CharReader { - private char cbuf[] = new char[1024]; - private int offset; - private int length; - private Reader reader; - private boolean eof; - private boolean hasNext; - private boolean isCR; - private char next; - private int line; - - public CharReader(Reader reader) { - this.reader = reader; - eof = false; - hasNext = false; - isCR = false; - line = 1; - } - - public char read() { - if (hasNext) { - hasNext = false; - return next; - } - - if (offset >= length) - readForward(); - if (eof) - return ' '; - else { - char c = cbuf[offset++]; - switch (c) { - case '\r': - isCR = true; - line++; - return '\n'; - case '\n': - if (isCR) { - isCR = false; - return read(); - } else { - line++; - return '\n'; - } - default: - isCR = false; - return c; - } - } - } - - public boolean isEof() { - return eof; - } - - public int getLine() { - if (hasNext && next == '\n') - return line - 1; - else - return line; - } - - public void close() { - try { - reader.close(); - } catch (IOException e) { - } - } - - public void pushBack(char c) { - hasNext = true; - next = c; - } - - private void readForward() { - if (eof) - return; - try { - length = reader.read(cbuf); - offset = 0; - if (length <= 0) - eof = true; - } catch (IOException e) { - eof = true; - } - } - } -} +/******************************************************************************* + * Copyright (c) 2012 VEditor Team + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * KOBAYASHI Tadashi - initial API and implementation + *******************************************************************************/ +package net.sourceforge.veditor.parser.verilog; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.resources.IFile; + +import net.sourceforge.veditor.parser.ParserReader; + +public class VerilogParserReader extends ParserReader { + private final static int CONTINUED = 0; + private final static int ELSE = 1; + private final static int ELSIF = 2; + private final static int ENDIF = 3; + + private CharReader reader; + private File directory; + private StringBuilder buffer; + private Map defines; + private boolean isInclude; + + public VerilogParserReader(InputStream in, IFile file) { + reader = new CharReader(new InputStreamReader(in)); + process(file); + reader.close(); + // System.out.println(buffer); + initialize(buffer.toString()); + } + + public VerilogParserReader(String text, IFile file) { + reader = new CharReader(new StringReader(text)); + process(file); + reader.close(); + // System.out.println(buffer); + initialize(buffer.toString()); + } + + private void process(IFile file) { + directory = file.getLocation().removeLastSegments(1).toFile(); + buffer = new StringBuilder(); + defines = new HashMap(); + isInclude = false; + + for (;;) { + if (reader.isEof()) + break; + // Normally it runs just once. It allows accidental `else or `endif + parseRegion(true); + } + } + + private static final int CODE = 0; + private static final int BLOCK_COMMENT = 1; + private static final int LINE_COMMENT = 2; + private static final int STRING = 3; + private static final int PROTECTED = 4; + + private String lastCode = ""; + + private int parseRegion(boolean enable) { + int context = CODE; + lastCode = ""; + + for (;;) { + if (reader.isEof()) { + return CONTINUED; + } + + char c = reader.read(); + lastCode += c; + + while (lastCode.length() > "pragma protect begin_protected".length()) { + lastCode = lastCode.substring(1); // remove the first element from the string + } + char next; + switch (c) { + case '\n': + if (context == LINE_COMMENT) { + context = CODE; + } + break; + case '"': + if (context == CODE) { + context = STRING; + } else if (context == STRING) { + context = CODE; + } + break; + case '/': + next = reader.read(); + if (next == '/' && context == CODE) + context = LINE_COMMENT; + else if (next == '*' && context == CODE) + context = BLOCK_COMMENT; + else + reader.pushBack(next); + break; + // detect the start of fully encrypted Verilog files + case '\u00e2' : + next = reader.read(); + if (next == '%' || next == '\u0013') { + context = PROTECTED; + + // stop parsing any further, read to the end of the file + reader.readForward(); + // stop parsing further + return CONTINUED; + } else { + reader.pushBack(next); + } + case '*': + next = reader.read(); + if (next == '/' && context == BLOCK_COMMENT) { + context = CODE; + c = ' '; + } else { + if (context != PROTECTED) { + reader.pushBack(next); + } + } + break; + } + if (c == '`' && context == CODE) { + int status = directive(enable); + if (status != CONTINUED) { + // if get `else `endif, return + return status; + } + } else { + if (c == '\n') { + if (isInclude) + buffer.append(' '); // for keeping line number + else + buffer.append('\n'); + } else if (enable && context != BLOCK_COMMENT + && context != LINE_COMMENT && context != PROTECTED) { + buffer.append(c); + } + } + + // search for the start marker + if (lastCode.contains("protect begin_protected") && (context != PROTECTED)) { + context = PROTECTED; + } + + // search for then end marker + if (lastCode.contains("protect end_protected") && (context == PROTECTED)) { + buffer.append("//pragma protect end_protected"); + context = CODE; + } + } + } + + private int directive(boolean enable) { + String cmd = getIdent(); + + if (cmd.equals("timescale") || cmd.equals("default_nettype")) { + getToEndOfLine(); + } else if (cmd.equals("define")) { + String def = getNextIdent(); + int line = reader.getLine(); + skipSpace(); + String value; + if (line == reader.getLine()) { + value = getToEndOfLine(); + int idx = value.indexOf("//"); + if (idx >= 0) + value = value.substring(0, idx); + } else { + value = ""; + } + if (enable) + defines.put(def, value); + } else if (cmd.equals("undef")) { + String def = getNextIdent(); + if (enable) + defines.remove(def); + } else if (cmd.equals("ifdef")) { + directiveIf(enable, true); + } else if (cmd.equals("ifndef")) { + directiveIf(enable, false); + } else if (cmd.equals("else")) { + return ELSE; + } else if (cmd.equals("elsif")) { + // parse next word on upper level + return ELSIF; + } else if (cmd.equals("endif")) { + return ENDIF; + } else if (cmd.equals("include")) { + String filename = getNextString(); + // System.out.println("include:" + filename); + directiveInclude(enable, filename); + } else { + // macro replace + if (enable) { + String value = defines.get(cmd); + if (value != null) { + buffer.append(value); + } else { + // not match + buffer.append('`'); + buffer.append(cmd); + // store in the lastcode + lastCode += cmd; + } + } + return CONTINUED; + } + return CONTINUED; + } + + private void directiveIf(boolean enable, boolean ifdef) { + String def = getNextIdent(); + boolean cond; + if (ifdef) + cond = (defines.get(def) != null); + else + cond = (defines.get(def) == null); + int status = parseRegion(enable && cond); + boolean done = cond; + while (status == ELSIF) { + def = getNextIdent(); + cond = (defines.get(def) != null); + status = parseRegion(enable && done == false && cond); + done = done || cond; + } + if (status == ELSE) { + parseRegion(enable && done == false); + } + } + + private void directiveInclude(boolean enable, String filename) { + if (enable == false) + return; + boolean storeIsInclude = isInclude; + CharReader storeReader = reader; + isInclude = true; + File file = new File(directory, filename); + try { + FileInputStream in = new FileInputStream(file); + reader = new CharReader(new InputStreamReader(in)); + parseRegion(true); + reader.close(); + } catch (IOException e) { + } + isInclude = storeIsInclude; + reader = storeReader; + } + + private String getIdent() { + StringBuffer word = new StringBuffer(); + char next = reader.read(); + while (Character.isJavaIdentifierPart(next)) { + word.append(next); + next = reader.read(); + } + reader.pushBack(next); + return word.toString(); + } + + private String getNextIdent() { + skipSpace(); + return getIdent(); + } + + private String getNextString() { + skipSpace(); + char next = reader.read(); + if (next != '"') + return ""; + StringBuffer word = new StringBuffer(); + next = reader.read(); + while (next != '"' && reader.isEof() == false) { + word.append(next); + next = reader.read(); + } + // consume last '"' + return word.toString(); + } + + private void skipSpace() { + char next = reader.read(); + while (Character.isWhitespace(next)) { + if (reader.isEof()) + return; + if (next == '\n' && isInclude == false) { + buffer.append('\n'); // for keeping line number + } + next = reader.read(); + } + reader.pushBack(next); + } + + private String getToEndOfLine() { + StringBuffer str = new StringBuffer(); + char next = reader.read(); + while (next != '\n' && reader.isEof() == false) { + str.append(next); + next = reader.read(); + } + if (isInclude == false) + buffer.append('\n'); // for keeping line number + return str.toString(); + } + + private static class CharReader { + private char cbuf[] = new char[1024]; + private int offset; + private int length; + private Reader reader; + private boolean eof; + private boolean hasNext; + private boolean isCR; + private char next; + private int line; + + public CharReader(Reader reader) { + this.reader = reader; + eof = false; + hasNext = false; + isCR = false; + line = 1; + } + + public char read() { + if (hasNext) { + hasNext = false; + return next; + } + + if (offset >= length) + readForward(); + if (eof) + return ' '; + else { + char c = cbuf[offset++]; + switch (c) { + case '\r': + isCR = true; + line++; + return '\n'; + case '\n': + if (isCR) { + isCR = false; + return read(); + } else { + line++; + return '\n'; + } + default: + isCR = false; + return c; + } + } + } + + public boolean isEof() { + return eof; + } + + public int getLine() { + if (hasNext && next == '\n') + return line - 1; + else + return line; + } + + public void close() { + try { + reader.close(); + } catch (IOException e) { + } + } + + public void pushBack(char c) { + hasNext = true; + next = c; + } + + private void readForward() { + if (eof) + return; + try { + length = reader.read(cbuf); + offset = 0; + if (length <= 0) + eof = true; + } catch (IOException e) { + eof = true; + } + } + } +}