summaryrefslogtreecommitdiffstats
path: root/src/antlr/com/jogamp/gluegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/antlr/com/jogamp/gluegen')
-rw-r--r--src/antlr/com/jogamp/gluegen/cgram/GnuCParser.g3
-rw-r--r--src/antlr/com/jogamp/gluegen/cgram/HeaderParser.g577
-rw-r--r--src/antlr/com/jogamp/gluegen/cgram/StdCParser.g15
-rw-r--r--src/antlr/com/jogamp/gluegen/jgram/JavaParser.g1509
4 files changed, 1177 insertions, 927 deletions
diff --git a/src/antlr/com/jogamp/gluegen/cgram/GnuCParser.g b/src/antlr/com/jogamp/gluegen/cgram/GnuCParser.g
index e8ca8c5..bf01b12 100644
--- a/src/antlr/com/jogamp/gluegen/cgram/GnuCParser.g
+++ b/src/antlr/com/jogamp/gluegen/cgram/GnuCParser.g
@@ -23,6 +23,7 @@ header {
import antlr.CommonAST;
import antlr.DumpASTVisitor;
+ import com.jogamp.gluegen.ASTLocusTag;
}
@@ -715,7 +716,7 @@ tokens {
public void addDefine(String name, String value)
{
- defines.add(new Define(name, value));
+ defines.add(new Define(name, value, new ASTLocusTag(lineObject.getSource(), lineObject.getLine()+deferredLineCount, -1, name)));
}
/** Returns a list of Define objects corresponding to the
diff --git a/src/antlr/com/jogamp/gluegen/cgram/HeaderParser.g b/src/antlr/com/jogamp/gluegen/cgram/HeaderParser.g
index 01f10c3..59eaca3 100644
--- a/src/antlr/com/jogamp/gluegen/cgram/HeaderParser.g
+++ b/src/antlr/com/jogamp/gluegen/cgram/HeaderParser.g
@@ -45,7 +45,14 @@ header {
import java.util.*;
import antlr.CommonAST;
+ import com.jogamp.gluegen.ASTLocusTag;
+ import com.jogamp.gluegen.ConstantDefinition;
+ import com.jogamp.gluegen.ConstantDefinition.CNumber;
+ import com.jogamp.gluegen.GlueGenException;
+ import com.jogamp.gluegen.JavaConfiguration;
import com.jogamp.gluegen.cgram.types.*;
+ import com.jogamp.gluegen.cgram.types.EnumType;
+ import com.jogamp.gluegen.cgram.types.EnumType.Enumerator;
}
class HeaderParser extends GnuCTreeParser;
@@ -67,6 +74,12 @@ options {
this.debug = debug;
}
+ /** Set the configuration for this
+ HeaderParser. Must be done before parsing. */
+ public void setJavaConfiguration(JavaConfiguration cfg) {
+ this.cfg = cfg;
+ }
+
/** Set the dictionary mapping typedef names to types for this
HeaderParser. Must be done before parsing. */
public void setTypedefDictionary(TypeDictionary dict) {
@@ -105,7 +118,7 @@ options {
// the enumerates from each EnumType, and fill in the enumHash
// so that each enumerate maps to the enumType to which it
// belongs.
- throw new RuntimeException("setEnums is Unimplemented!");
+ throw new RuntimeException("setEnums is Unimplemented!");
}
/** Returns the EnumTypes this HeaderParser processed. */
@@ -125,22 +138,25 @@ options {
return functions;
}
- private CompoundType lookupInStructDictionary(String typeName,
+ private CompoundType lookupInStructDictionary(String structName,
CompoundTypeKind kind,
- int cvAttrs) {
- CompoundType t = (CompoundType) structDictionary.get(typeName);
+ int cvAttrs, final ASTLocusTag locusTag)
+ {
+ CompoundType t = (CompoundType) structDictionary.get(structName);
if (t == null) {
- t = CompoundType.create(null, null, kind, cvAttrs);
- t.setStructName(typeName);
- structDictionary.put(typeName, t);
+ t = CompoundType.create(structName, null, kind, cvAttrs, locusTag);
+ structDictionary.put(structName, t);
+ debugPrintln("Adding compound mapping: [" + structName + "] -> "+getDebugTypeString(t)+" @ "+locusTag);
+ debugPrintln(t.getStructString());
}
return t;
}
- private Type lookupInTypedefDictionary(String typeName) {
+ private Type lookupInTypedefDictionary(final AST _t, String typeName) {
Type t = typedefDictionary.get(typeName);
if (t == null) {
- throw new RuntimeException("Undefined reference to typedef name " + typeName);
+ throwGlueGenException(_t,
+ "Undefined reference to typedef name " + typeName);
}
return t;
}
@@ -153,8 +169,10 @@ options {
this.id = id;
this.type = type;
}
- String id() { return id; }
- Type type() { return type; }
+ String id() { return id; }
+ Type type() { return type; }
+ void setType(final Type t) { type = t; }
+ public String toString() { return "ParamDecl["+id+": "+type.getDebugString()+"]"; }
}
// A box for a Type. Allows type to be passed down to be modified by recursive rules.
@@ -207,22 +225,27 @@ options {
}
}
+ private String getDebugTypeString(Type t) {
+ if(debug) {
+ return getTypeString(t);
+ } else {
+ return null;
+ }
+ }
private String getTypeString(Type t) {
StringBuilder sb = new StringBuilder();
sb.append("[");
- sb.append(t);
- sb.append(", size: ");
if(null!=t) {
- SizeThunk st = t.getSize();
- if(null!=st) {
- sb.append(st.getClass().getName());
- } else {
- sb.append("undef");
- }
+ sb.append(t.getDebugString());
+ sb.append(", opaque ").append(isOpaque(t)).append("]");
+ } else {
+ sb.append("nil]");
}
- sb.append("]");
return sb.toString();
}
+ private boolean isOpaque(final Type type) {
+ return (cfg.typeInfo(type) != null);
+ }
private void debugPrintln(String msg) {
if(debug) {
@@ -236,14 +259,13 @@ options {
}
}
- private boolean doDeclaration; // Used to only process function typedefs
- private String declId;
- private List parameters;
+ private JavaConfiguration cfg;
private TypeDictionary typedefDictionary;
private TypeDictionary structDictionary;
private List<FunctionSymbol> functions = new ArrayList<FunctionSymbol>();
// hash from name of an enumerated value to the EnumType to which it belongs
private HashMap<String, EnumType> enumHash = new HashMap<String, EnumType>();
+ private HashMap<String, EnumType> enumMap = new HashMap<String, EnumType>();
// Storage class specifiers
private static final int AUTO = 1 << 0;
@@ -259,25 +281,41 @@ options {
private static final int SIGNED = 1 << 8;
private static final int UNSIGNED = 1 << 9;
- private void initDeclaration() {
- doDeclaration = false;
- declId = null;
- }
+ private boolean isFuncDeclaration; // Used to only process function typedefs
+ private String funcDeclName;
+ private List<ParameterDeclaration> funcDeclParams;
+ private ASTLocusTag funcLocusTag;
- private void doDeclaration() {
- doDeclaration = true;
+ private void resetFuncDeclaration() {
+ isFuncDeclaration = false;
+ funcDeclName = null;
+ funcDeclParams = null;
+ funcLocusTag = null;
+ }
+ private void setFuncDeclaration(final String name, final List<ParameterDeclaration> p, final ASTLocusTag locusTag) {
+ isFuncDeclaration = true;
+ funcDeclName = name;
+ funcDeclParams = p;
+ funcLocusTag = locusTag;
}
private void processDeclaration(Type returnType) {
- if (doDeclaration) {
- FunctionSymbol sym = new FunctionSymbol(declId, new FunctionType(null, null, returnType, 0));
- if (parameters != null) { // handle funcs w/ empty parameter lists (e.g., "foo()")
- for (Iterator iter = parameters.iterator(); iter.hasNext(); ) {
- ParameterDeclaration pd = (ParameterDeclaration) iter.next();
+ if (isFuncDeclaration) {
+ final FunctionSymbol sym = new FunctionSymbol(funcDeclName,
+ new FunctionType(null, null, returnType, 0, funcLocusTag),
+ funcLocusTag);
+ debugPrintln("Function ... "+sym.toString()+" @ "+funcLocusTag);
+ if (funcDeclParams != null) { // handle funcs w/ empty parameter lists (e.g., "foo()")
+ for (Iterator<ParameterDeclaration> iter = funcDeclParams.iterator(); iter.hasNext(); ) {
+ ParameterDeclaration pd = iter.next();
+ pd.setType(pd.type());
+ debugPrintln(" add "+pd.toString());
sym.addArgument(pd.type(), pd.id());
}
- }
+ }
+ debugPrintln("Function Added "+sym.toString());
functions.add(sym);
+ resetFuncDeclaration();
}
}
@@ -294,19 +332,18 @@ options {
/** Helper routine which handles creating a pointer or array type
for [] expressions */
- private void handleArrayExpr(TypeBox tb, AST t) {
+ private void handleArrayExpr(TypeBox tb, AST t, ASTLocusTag locusTag) {
if (t != null) {
try {
final int len = parseIntConstExpr(t);
- tb.setType(canonicalize(new ArrayType(tb.type(), SizeThunk.mul(SizeThunk.constant(len), tb.type().getSize()), len, 0)));
+ tb.setType(canonicalize(new ArrayType(tb.type(), SizeThunk.mul(SizeThunk.constant(len), tb.type().getSize()), len, 0, locusTag)));
return;
} catch (RecognitionException e) {
// Fall through
}
}
tb.setType(canonicalize(new PointerType(SizeThunk.POINTER,
- tb.type(),
- 0)));
+ tb.type(), 0, locusTag)));
}
private int parseIntConstExpr(AST t) throws RecognitionException {
@@ -315,49 +352,104 @@ options {
/** Utility function: creates a new EnumType with the given name, or
returns an existing one if it has already been created. */
- private EnumType getEnumType(String enumTypeName) {
+ private EnumType getEnumType(String enumTypeName, ASTLocusTag locusTag) {
EnumType enumType = null;
Iterator<EnumType> it = enumHash.values().iterator();
while (it.hasNext()) {
EnumType potentialMatch = it.next();
if (potentialMatch.getName().equals(enumTypeName)) {
- enumType = potentialMatch;
- break;
+ enumType = potentialMatch;
+ break;
}
}
if (enumType == null) {
- // This isn't quite correct. In theory the enum should expand to
- // the size of the largest element, so if there were a long long
- // entry the enum should expand to e.g. int64. However, using
- // "long" here (which is what used to be the case) was
- // definitely incorrect and caused problems.
- enumType = new EnumType(enumTypeName, SizeThunk.INT32);
+ // This isn't quite correct. In theory the enum should expand to
+ // the size of the largest element, so if there were a long long
+ // entry the enum should expand to e.g. int64. However, using
+ // "long" here (which is what used to be the case) was
+ // definitely incorrect and caused problems.
+ enumType = new EnumType(enumTypeName, SizeThunk.INT32, locusTag);
}
return enumType;
- }
+ }
// Map used to canonicalize types. For example, we may typedef
// struct foo { ... } *pfoo; subsequent references to struct foo* should
// point to the same PointerType object that had its name set to "pfoo".
- private Map canonMap = new HashMap();
+ // Opaque canonical types are excluded.
+ private Map<Type, Type> canonMap = new HashMap<Type, Type>();
private Type canonicalize(Type t) {
Type res = (Type) canonMap.get(t);
if (res != null) {
return res;
+ } else {
+ canonMap.put(t, t);
+ return t;
+ }
+ }
+
+ private void throwGlueGenException(final AST t, final String message) throws GlueGenException {
+ // dumpASTTree("XXX", t);
+ throw new GlueGenException(message, findASTLocusTag(t));
+ }
+ private void throwGlueGenException(final ASTLocusTag locusTag, final String message) throws GlueGenException {
+ // dumpASTTree("XXX", t);
+ throw new GlueGenException(message, locusTag);
+ }
+
+ /**
+ * Return ASTLocusTag in tree, or null if not found.
+ */
+ private ASTLocusTag findASTLocusTag(final AST astIn) {
+ AST ast = astIn;
+ while(null != ast) {
+ if( ast instanceof TNode ) {
+ final TNode tn = (TNode) ast;
+ final ASTLocusTag tag = tn.getASTLocusTag();
+ if( null != tag ) {
+ return tag;
+ }
+ }
+ ast = ast.getFirstChild();
+ }
+ return null;
+ }
+ private void dumpASTTree(final String pre, final AST t) {
+ int i=0;
+ AST it = t;
+ while( null != it ) {
+ it = dumpAST(pre+"."+i, it);
+ i++;
+ }
+ }
+ private AST dumpAST(final String pre, final AST ast) {
+ if( null == ast ) {
+ System.err.println(pre+".0: AST NULL");
+ return null;
+ } else {
+ System.err.println(pre+".0: AST Type: "+ast.getClass().getName());
+ System.err.println(pre+".1: line:col "+ast.getLine()+":"+ast.getColumn()+" -> "+ast.getText());
+ if( ast instanceof TNode ) {
+ final TNode tn = (TNode) ast;
+ final ASTLocusTag tag = tn.getASTLocusTag();
+ System.err.println(pre+".TN.1: "+tag);
+ final Hashtable<String, Object> attributes = tn.getAttributesTable();
+ System.err.println(pre+".TN.2: "+attributes);
+ }
+ return ast.getFirstChild();
}
- canonMap.put(t, t);
- return t;
}
}
declarator[TypeBox tb] returns [String s] {
- initDeclaration();
+ resetFuncDeclaration();
s = null;
- List params = null;
+ List<ParameterDeclaration> params = null;
String funcPointerName = null;
TypeBox dummyTypeBox = null;
+ final ASTLocusTag locusTag = findASTLocusTag(declarator_AST_in);
}
: #( NDeclarator
( pointerGroup[tb] )?
@@ -374,32 +466,29 @@ declarator[TypeBox tb] returns [String s] {
RPAREN
) {
if (id != null) {
- declId = id.getText();
- parameters = params; // FIXME: Ken, why are we setting this class member here?
- doDeclaration();
+ setFuncDeclaration(id.getText(), params, locusTag);
} else if ( funcPointerName != null ) {
/* TypeBox becomes function pointer in this case */
- FunctionType ft = new FunctionType(null, null, tb.type(), 0);
+ final FunctionType ft = new FunctionType(null, null, tb.type(), 0, locusTag);
if (params == null) {
- // If the function pointer has no declared parameters, it's a
- // void function. I'm not sure if the parameter name is
- // ever referenced anywhere when the type is VoidType, so
+ // If the function pointer has no declared parameters, it's a
+ // void function. I'm not sure if the parameter name is
+ // ever referenced anywhere when the type is VoidType, so
// just in case I'll set it to a comment string so it will
- // still compile if written out to code anywhere.
- ft.addArgument(new VoidType(0), "/*unnamed-void*/");
- } else {
- for (Iterator iter = params.iterator(); iter.hasNext(); ) {
- ParameterDeclaration pd = (ParameterDeclaration) iter.next();
- ft.addArgument(pd.type(), pd.id());
- }
+ // still compile if written out to code anywhere.
+ ft.addArgument(new VoidType(0, locusTag), "/*unnamed-void*/");
+ } else {
+ for (Iterator iter = params.iterator(); iter.hasNext(); ) {
+ ParameterDeclaration pd = (ParameterDeclaration) iter.next();
+ ft.addArgument(pd.type(), pd.id());
+ }
}
tb.setType(canonicalize(new PointerType(SizeThunk.POINTER,
- ft,
- 0)));
+ ft, 0, locusTag)));
s = funcPointerName;
}
}
- | LBRACKET ( e:expr )? RBRACKET { handleArrayExpr(tb, e); }
+ | LBRACKET ( e:expr )? RBRACKET { handleArrayExpr(tb, e, locusTag); }
)*
)
;
@@ -422,8 +511,8 @@ declaration {
) { processDeclaration(tb.type()); }
;
-parameterTypeList returns [List l] { l = new ArrayList(); ParameterDeclaration decl = null; }
- : ( decl = parameterDeclaration { if (decl != null) l.add(decl); } ( COMMA | SEMI )? )+ ( VARARGS )?
+parameterTypeList returns [List<ParameterDeclaration> l] { l = new ArrayList<ParameterDeclaration>(); ParameterDeclaration decl = null; }
+ : ( decl = parameterDeclaration { if (decl != null) { l.add(decl); } } ( COMMA | SEMI )? )+ ( VARARGS )?
;
parameterDeclaration returns [ParameterDeclaration pd] {
@@ -435,7 +524,13 @@ parameterDeclaration returns [ParameterDeclaration pd] {
: #( NParameterDeclaration
tb = declSpecifiers
(decl = declarator[tb] | nonemptyAbstractDeclarator[tb])?
- ) { pd = new ParameterDeclaration(decl, tb.type()); }
+ ) {
+ if( null == tb ) {
+ throwGlueGenException(parameterDeclaration_AST_in,
+ String.format("Undefined type for declaration '%s'", decl));
+ }
+ pd = new ParameterDeclaration(decl, tb.type());
+ }
;
functionDef {
@@ -462,7 +557,10 @@ declSpecifiers returns [TypeBox tb] {
{
if (t == null &&
(x & (SIGNED | UNSIGNED)) != 0) {
- t = new IntType("int", SizeThunk.INTxx, ((x & UNSIGNED) != 0), attrs2CVAttrs(x));
+ t = new IntType("int", SizeThunk.INTxx,
+ ((x & UNSIGNED) != 0),
+ attrs2CVAttrs(x),
+ findASTLocusTag(declSpecifiers_AST_in));
}
tb = new TypeBox(t, ((x & TYPEDEF) != 0));
}
@@ -493,30 +591,35 @@ typeQualifier returns [int x] { x = 0; }
typeSpecifier[int attributes] returns [Type t] {
t = null;
int cvAttrs = attrs2CVAttrs(attributes);
- boolean unsigned = ((attributes & UNSIGNED) != 0);
+ boolean unsig = ((attributes & UNSIGNED) != 0);
+ final ASTLocusTag locusTag = findASTLocusTag(typeSpecifier_AST_in);
}
- : "void" { t = new VoidType(cvAttrs); }
- | "char" { t = new IntType("char" , SizeThunk.INT8, unsigned, cvAttrs); }
- | "short" { t = new IntType("short", SizeThunk.INT16, unsigned, cvAttrs); }
- | "int" { t = new IntType("int" , SizeThunk.INTxx, unsigned, cvAttrs); }
- | "long" { t = new IntType("long" , SizeThunk.LONG, unsigned, cvAttrs); }
- | "float" { t = new FloatType("float", SizeThunk.FLOAT, cvAttrs); }
- | "double" { t = new DoubleType("double", SizeThunk.DOUBLE, cvAttrs); }
- | "__int32" { t = new IntType("__int32", SizeThunk.INT32, unsigned, cvAttrs); }
- | "__int64" { t = new IntType("__int64", SizeThunk.INT64, unsigned, cvAttrs); }
- | "int8_t" { t = new IntType("int8_t", SizeThunk.INT8, false, cvAttrs); /* TS: always signed */ }
- | "uint8_t" { t = new IntType("uint8_t", SizeThunk.INT8, true, cvAttrs); /* TS: always unsigned */ }
- | "int16_t" { t = new IntType("int16_t", SizeThunk.INT16, false, cvAttrs); /* TS: always signed */ }
- | "uint16_t" { t = new IntType("uint16_t", SizeThunk.INT16, true, cvAttrs); /* TS: always unsigned */ }
- | "int32_t" { t = new IntType("int32_t", SizeThunk.INT32, false, cvAttrs); /* TS: always signed */ }
- | "wchar_t" { t = new IntType("wchar_t", SizeThunk.INT32, false, cvAttrs); /* TS: always signed */ }
- | "uint32_t" { t = new IntType("uint32_t", SizeThunk.INT32, true, cvAttrs, true); /* TS: always unsigned */ }
- | "int64_t" { t = new IntType("int64_t", SizeThunk.INT64, false, cvAttrs); /* TS: always signed */ }
- | "uint64_t" { t = new IntType("uint64_t", SizeThunk.INT64, true, cvAttrs, true); /* TS: always unsigned */ }
- | "ptrdiff_t" { t = new IntType("ptrdiff_t", SizeThunk.POINTER, false, cvAttrs); /* TS: always signed */ }
- | "intptr_t" { t = new IntType("intptr_t", SizeThunk.POINTER, false, cvAttrs); /* TS: always signed */ }
- | "size_t" { t = new IntType("size_t", SizeThunk.POINTER, true, cvAttrs, true); /* TS: always unsigned */ }
- | "uintptr_t" { t = new IntType("uintptr_t", SizeThunk.POINTER, true, cvAttrs, true); /* TS: always unsigned */ }
+ // TYPEDEF
+ // | TYPEDEF-UNSIGNED
+ // UNSIGNED | |
+ // TOKEN TYPE NAME SIZE | ATTRIBS | | LOCUS
+ : "void" { t = new VoidType( cvAttrs, locusTag); }
+ | "char" { t = new IntType("char" , SizeThunk.INT8, unsig, cvAttrs, false, false, locusTag); }
+ | "short" { t = new IntType("short", SizeThunk.INT16, unsig, cvAttrs, false, false, locusTag); }
+ | "int" { t = new IntType("int" , SizeThunk.INTxx, unsig, cvAttrs, false, false, locusTag); }
+ | "long" { t = new IntType("long" , SizeThunk.LONG, unsig, cvAttrs, false, false, locusTag); }
+ | "float" { t = new FloatType("float", SizeThunk.FLOAT, cvAttrs, locusTag); }
+ | "double" { t = new DoubleType("double", SizeThunk.DOUBLE, cvAttrs, locusTag); }
+ | "__int32" { t = new IntType("__int32", SizeThunk.INT32, unsig, cvAttrs, true, false, locusTag); } /* TD: signed */
+ | "__int64" { t = new IntType("__int64", SizeThunk.INT64, unsig, cvAttrs, true, false, locusTag); } /* TD: signed */
+ | "int8_t" { t = new IntType("int8_t", SizeThunk.INT8, unsig, cvAttrs, true, false, locusTag); } /* TD: signed */
+ | "uint8_t" { t = new IntType("uint8_t", SizeThunk.INT8, unsig, cvAttrs, true, true, locusTag); } /* TD: unsigned */
+ | "int16_t" { t = new IntType("int16_t", SizeThunk.INT16, unsig, cvAttrs, true, false, locusTag); } /* TD: signed */
+ | "uint16_t" { t = new IntType("uint16_t", SizeThunk.INT16, unsig, cvAttrs, true, true, locusTag); } /* TD: unsigned */
+ | "int32_t" { t = new IntType("int32_t", SizeThunk.INT32, unsig, cvAttrs, true, false, locusTag); } /* TD: signed */
+ | "wchar_t" { t = new IntType("wchar_t", SizeThunk.INT32, unsig, cvAttrs, true, false, locusTag); } /* TD: signed */
+ | "uint32_t" { t = new IntType("uint32_t", SizeThunk.INT32, unsig, cvAttrs, true, true, locusTag); } /* TS: unsigned */
+ | "int64_t" { t = new IntType("int64_t", SizeThunk.INT64, unsig, cvAttrs, true, false, locusTag); } /* TD: signed */
+ | "uint64_t" { t = new IntType("uint64_t", SizeThunk.INT64, unsig, cvAttrs, true, true, locusTag); } /* TD: unsigned */
+ | "ptrdiff_t" { t = new IntType("ptrdiff_t", SizeThunk.POINTER, unsig, cvAttrs, true, false, locusTag); } /* TD: signed */
+ | "intptr_t" { t = new IntType("intptr_t", SizeThunk.POINTER, unsig, cvAttrs, true, false, locusTag); } /* TD: signed */
+ | "size_t" { t = new IntType("size_t", SizeThunk.POINTER, unsig, cvAttrs, true, true, locusTag); } /* TD: unsigned */
+ | "uintptr_t" { t = new IntType("uintptr_t", SizeThunk.POINTER, unsig, cvAttrs, true, true, locusTag); } /* TD: unsigned */
| t = structSpecifier[cvAttrs] ( attributeDecl )*
| t = unionSpecifier [cvAttrs] ( attributeDecl )*
| t = enumSpecifier [cvAttrs]
@@ -533,9 +636,12 @@ typeSpecifier[int attributes] returns [Type t] {
typedefName[int cvAttrs] returns [Type t] { t = null; }
: #(NTypedefName id : ID)
{
- Type tdict = lookupInTypedefDictionary(id.getText());
- t = canonicalize(tdict.getCVVariant(cvAttrs));
- debugPrintln("Adding typedef canon : [" + id.getText() + "] -> [" + tdict + "] -> "+getTypeString(t));
+ final Type t0 = lookupInTypedefDictionary(typedefName_AST_in, id.getText());
+ debugPrint("Adding typedef lookup: [" + id.getText() + "] -> "+getDebugTypeString(t0));
+ final Type t1 = t0.newCVVariant(cvAttrs);
+ debugPrintln(" - cvvar -> "+getDebugTypeString(t1));
+ t = canonicalize(t1);
+ debugPrintln(" - canon -> "+getDebugTypeString(t));
}
;
@@ -549,31 +655,50 @@ unionSpecifier[int cvAttrs] returns [Type t] { t = null; }
structOrUnionBody[CompoundTypeKind kind, int cvAttrs] returns [CompoundType t] {
t = null;
+ boolean addedAny = false;
+ final ASTLocusTag locusTag = findASTLocusTag(structOrUnionBody_AST_in);
}
: ( (ID LCURLY) => id:ID LCURLY {
- t = (CompoundType) canonicalize(lookupInStructDictionary(id.getText(), kind, cvAttrs));
- } ( structDeclarationList[t] )?
+ // fully declared struct, i.e. not anonymous
+ t = (CompoundType) canonicalize(lookupInStructDictionary(id.getText(), kind, cvAttrs, locusTag));
+ } ( addedAny = structDeclarationList[t] )?
RCURLY { t.setBodyParsed(); }
- | LCURLY { t = CompoundType.create(null, null, kind, cvAttrs); }
- ( structDeclarationList[t] )?
+ | LCURLY {
+ // anonymous declared struct
+ t = CompoundType.create(null, null, kind, cvAttrs, locusTag);
+ } ( structDeclarationList[t] )?
RCURLY { t.setBodyParsed(); }
- | id2:ID { t = (CompoundType) canonicalize(lookupInStructDictionary(id2.getText(), kind, cvAttrs)); }
- )
+ | id2:ID {
+ // anonymous struct
+ t = (CompoundType) canonicalize(lookupInStructDictionary(id2.getText(), kind, cvAttrs, locusTag));
+ }
+ ) {
+ debugPrintln("Adding compound body: [" + t.getName() + "] -> "+getDebugTypeString(t)+" @ "+locusTag);
+ debugPrintln(t.getStructString());
+ }
;
-structDeclarationList[CompoundType t]
- : ( structDeclaration[t] )+
+structDeclarationList[CompoundType t] returns [boolean addedAny] {
+ addedAny = false;
+ boolean addedOne = false;
+}
+ : ( addedOne = structDeclaration[t] { addedAny |= addedOne; } )+
;
-structDeclaration[CompoundType containingType] {
+structDeclaration[CompoundType containingType] returns [boolean addedAny] {
+ addedAny = false;
Type t = null;
- boolean addedAny = false;
}
: t = specifierQualifierList addedAny = structDeclaratorList[containingType, t] {
if (!addedAny) {
if (t != null) {
CompoundType ct = t.asCompound();
- if (ct.isUnion()) {
+ if( null == ct ) {
+ throwGlueGenException(structDeclaration_AST_in,
+ String.format("Anonymous compound, w/ NULL type:%n containing '%s'",
+ getTypeString(containingType)));
+ }
+ if ( ct.isUnion() ) {
// Anonymous union
containingType.addField(new Field(null, t, null));
}
@@ -591,7 +716,8 @@ specifierQualifierList returns [Type t] {
)+ {
if (t == null &&
(x & (SIGNED | UNSIGNED)) != 0) {
- t = new IntType("int", SizeThunk.INTxx, ((x & UNSIGNED) != 0), attrs2CVAttrs(x));
+ t = new IntType("int", SizeThunk.INTxx, ((x & UNSIGNED) != 0), attrs2CVAttrs(x),
+ findASTLocusTag(specifierQualifierList_AST_in));
}
}
;
@@ -616,7 +742,7 @@ structDeclarator[CompoundType containingType, Type t] returns [boolean addedAny]
)
;
-// FIXME: this will not correctly set the name of the enumeration when
+// This will not correctly set the name of the enumeration when
// encountering a declaration like this:
//
// typedef enum { } enumName;
@@ -625,65 +751,88 @@ structDeclarator[CompoundType containingType, Type t] returns [boolean addedAny]
// incorrectly return HeaderParser.ANONYMOUS_ENUM_NAME instead of
// "enumName"
//
-// I haven't implemented it yet because I'm not sure how to get the
-// "enumName" *before* executing the enumList rule.
+// The followup typedef, see 'initDecl', will alias this name,
+// hence correct the issue!
enumSpecifier [int cvAttrs] returns [Type t] {
t = null;
+ EnumType e = null;
+ ASTLocusTag locusTag = findASTLocusTag(enumSpecifier_AST_in);
}
: #( "enum"
- ( ( ID LCURLY )=> i:ID LCURLY enumList[(EnumType)(t = getEnumType(i.getText()))] RCURLY
- | LCURLY enumList[(EnumType)(t = getEnumType(ANONYMOUS_ENUM_NAME))] RCURLY
- | ID { t = getEnumType(i.getText()); }
- )
- )
+ ( ( ID LCURLY )=> i:ID LCURLY enumList[(EnumType)(e = getEnumType(i.getText(), locusTag))] RCURLY
+ | LCURLY enumList[(EnumType)(e = getEnumType(ANONYMOUS_ENUM_NAME, locusTag))] RCURLY
+ | ID { e = getEnumType(i.getText(), locusTag); }
+ ) {
+ debugPrintln("Adding enum mapping: "+getDebugTypeString(e));
+ if( null != e ) {
+ final String eName = e.getName();
+ if( null != eName && !eName.equals(ANONYMOUS_ENUM_NAME) ) { // validate only non-anonymous enum
+ final EnumType dupE = enumMap.get(eName);
+ if( null != dupE && !dupE.equalSemantics(e) ) {
+ throwGlueGenException(enumSpecifier_AST_in,
+ String.format("Duplicate enum w/ incompatible type:%n this '%s',%n have '%s',%n %s: previous definition is here",
+ getTypeString(e), getTypeString(dupE), dupE.getASTLocusTag().toString(new StringBuilder(), "note", true)));
+ }
+ enumMap.put(eName, (EnumType)e.clone(locusTag));
+ }
+ }
+ t = e; // return val
+ }
+ )
;
enumList[EnumType enumeration] {
- long defaultEnumerantValue = 0;
+ ConstantDefinition defEnumerant = new ConstantDefinition("def", "0", new CNumber(true, false, 0), findASTLocusTag(enumList_AST_in));
}
- : ( defaultEnumerantValue = enumerator[enumeration, defaultEnumerantValue] )+
+ : ( defEnumerant = enumerator[enumeration, defEnumerant] )+
;
-enumerator[EnumType enumeration, long defaultValue] returns [long newDefaultValue] {
+enumerator[EnumType enumeration, ConstantDefinition defaultValue] returns [ConstantDefinition newDefaultValue] {
newDefaultValue = defaultValue;
}
: eName:ID ( ASSIGN eVal:expr )? {
- long value = 0;
+ final String eTxt = eName.getText();
+ final Enumerator newEnum;
if (eVal != null) {
- String vTxt = eVal.getAllChildrenText();
+ String vTxt = eVal.getAllChildrenText(eTxt);
if (enumHash.containsKey(vTxt)) {
EnumType oldEnumType = enumHash.get(vTxt);
- value = oldEnumType.getEnumValue(vTxt);
+ Enumerator oldEnum = oldEnumType.getEnum(vTxt);
+ newEnum = oldEnum;
} else {
- try {
- value = Long.decode(vTxt).longValue();
- } catch (NumberFormatException e) {
- System.err.println("NumberFormatException: ID[" + eName.getText() + "], VALUE=[" + vTxt + "]");
- throw e;
- }
+ newEnum = new Enumerator(eTxt, vTxt);
}
+ } else if( defaultValue.hasNumber() ) {
+ newEnum = new Enumerator(eTxt, defaultValue.getNumber());
} else {
- value = defaultValue;
+ newEnum = new Enumerator(eTxt, defaultValue.getNativeExpr());
}
-
- newDefaultValue = value+1;
- String eTxt = eName.getText();
- if (enumHash.containsKey(eTxt)) {
- EnumType oldEnumType = enumHash.get(eTxt);
- long oldValue = oldEnumType.getEnumValue(eTxt);
- System.err.println("WARNING: redefinition of enumerated value '" + eTxt + "';" +
- " existing definition is in enumeration '" + oldEnumType.getName() +
- "' with value " + oldValue + " and new definition is in enumeration '" +
- enumeration.getName() + "' with value " + value);
- // remove old definition
- oldEnumType.removeEnumerate(eTxt);
- }
- // insert new definition
- enumeration.addEnum(eTxt, value);
- enumHash.put(eTxt, enumeration);
- debugPrintln("ENUM [" + enumeration.getName() + "]: " + eTxt + " = " + enumeration.getEnumValue(eTxt) +
- " (new default = " + newDefaultValue + ")");
- }
+ final ASTLocusTag locus = findASTLocusTag(enumerator_AST_in);
+ final CNumber newEnumNum = newEnum.getNumber();
+ if( null != newEnumNum && newEnumNum.isInteger ) {
+ final long n = newEnumNum.i+1;
+ newDefaultValue = new ConstantDefinition("def", String.valueOf(n), new CNumber(newEnumNum.isLong, newEnumNum.isUnsigned, n), locus);
+ } else {
+ newDefaultValue = new ConstantDefinition("def", "("+newEnum.getExpr()+")+1", null, locus);
+ }
+ if (enumHash.containsKey(eTxt)) {
+ EnumType oldEnumType = enumHash.get(eTxt);
+ final Enumerator oldEnum = oldEnumType.getEnum(eTxt);
+ final String oldExpr = oldEnum.getExpr();
+ if( !oldExpr.equals(newEnum.getExpr()) ) {
+ throwGlueGenException(enumerator_AST_in,
+ String.format("Duplicate enum value '%s.%s' w/ diff value:%n this %s,%n have %s",
+ oldEnumType.getName(), eTxt, newEnum, oldEnum));
+ }
+ // remove old definition
+ oldEnumType.removeEnumerate(eTxt);
+ }
+ // insert new definition
+ enumeration.addEnum(eTxt, newEnum);
+ enumHash.put(eTxt, enumeration);
+ debugPrintln("ENUM [" + enumeration.getName() + "]: " + eTxt + " = " + newEnum +
+ " (new default = " + newDefaultValue + ")");
+ }
;
initDeclList[TypeBox tb]
@@ -692,6 +841,7 @@ initDeclList[TypeBox tb]
initDecl[TypeBox tb] {
String declName = null;
+ final ASTLocusTag locusTag = findASTLocusTag(initDecl_AST_in);
}
: #( NInitDecl
declName = declarator[tb] {
@@ -705,23 +855,99 @@ initDecl[TypeBox tb] {
{
if ((declName != null) && (tb != null) && tb.isTypedef()) {
Type t = tb.type();
- debugPrint("Adding typedef mapping: [" + declName + "] -> "+getTypeString(t));
- if (!t.hasTypedefName()) {
- t.setName(declName);
- debugPrint(" - declName -> "+getTypeString(t));
+ debugPrintln("Adding typedef mapping: [" + declName + "] -> "+getDebugTypeString(t));
+ final Type tg;
+ if( t.isPointer() ) {
+ tg = t.getTargetType();
+ debugPrintln(" - has target: "+getDebugTypeString(tg));
} else {
- // copy type to preserve declName !
- t = (Type) t.clone();
- t.setName(declName);
- debugPrint(" - copy -> "+getTypeString(t));
+ tg = null;
+ }
+ // NOTE: Struct Name Resolution (JavaEmitter, HeaderParser)
+ // Also see NOTE below.
+ if (!t.isTypedef()) {
+ if( t.isCompound() || t.isEnum() ) {
+ // This aliases '_a' -> 'A' for 'typedef struct _a { } A;' in-place
+ // This aliases '_a' -> 'A' for 'typedef enum _a { } A;' in-place
+ t.setTypedefName(declName);
+ debugPrintln(" - alias.11 -> "+getDebugTypeString(t));
+ } else {
+ // Use new typedef, using a copy to preserve canonicalized base type
+ t = t.clone(locusTag);
+ t.setTypedefName(declName);
+ debugPrintln(" - newdefine.12 -> "+getDebugTypeString(t));
+ }
+ } else {
+ // Adds typeInfo alias w/ t's typeInfo, if exists
+ cfg.addTypeInfo(declName, t);
+ final Type alias;
+ if( t.isCompound() ) {
+ // This aliases 'D' -> 'A' for 'typedef struct _a { } A, D;' in-place
+ debugPrintln(" - alias.21 -> "+getDebugTypeString(t));
+ } else {
+ // copy to preserve canonicalized base type
+ t = t.clone(locusTag);
+ t.setTypedefName(declName);
+ debugPrintln(" - copy.22 -> "+getDebugTypeString(t));
+ }
+ }
+ final Type dupT = typedefDictionary.get(declName);
+ if( null != dupT && !dupT.equalSemantics(t) ) {
+ throwGlueGenException(locusTag,
+ String.format("Duplicate typedef w/ incompatible type:%n this '%s',%n have '%s',%n %s: previous definition is here",
+ getTypeString(t), getTypeString(dupT), dupT.getASTLocusTag().toString(new StringBuilder(), "note", true)));
}
t = canonicalize(t);
- debugPrintln(" - canon -> "+getTypeString(t));
+ debugPrintln(" - canon -> "+getDebugTypeString(t));
typedefDictionary.put(declName, t);
// Clear out PointerGroup effects in case another typedef variant follows
tb.reset();
}
}
+ /*
+ // Below just shows a different handling using copying
+ // and enforcing aliased names, which is not desired.
+ // Keeping it in here for documentation.
+ // NOTE: Struct Name Resolution (JavaEmitter, HeaderParser)
+ if ( !t.isTypedef() ) {
+ if( t.isCompound() ) {
+ // This aliases '_a' -> 'A' for 'typedef struct _a { } A;'
+ t.setTypedefName(declName);
+ debugPrintln(" - alias.10 -> "+getDebugTypeString(t));
+ } else if( null != tg && tg.isCompound() ) {
+ if( !tg.isTypedef() ) {
+ // This aliases '_a *' -> 'A*' for 'typedef struct _a { } *A;'
+ t.setTypedefName(declName);
+ debugPrintln(" - alias.11 -> "+getDebugTypeString(t));
+ } else {
+ // This aliases 'B' -> 'A*' for 'typedef struct _a { } A, *B;' and 'typedef A * B;'
+ t = new PointerType(SizeThunk.POINTER, tg, 0, locusTag); // name: 'A*'
+ t.setTypedefName(t.getName()); // make typedef
+ debugPrintln(" - alias.12 -> "+getDebugTypeString(t));
+ }
+ } else {
+ // Use new typedef, using a copy to preserve canonicalized base type
+ t = t.clone(locusTag);
+ t.setTypedefName(declName);
+ debugPrintln(" - newdefine.13 -> "+getDebugTypeString(t));
+ }
+ } else {
+ // Adds typeInfo alias w/ t's typeInfo, if exists
+ cfg.addTypeInfo(declName, t);
+ if( t.isCompound() ) {
+ // This aliases 'D' -> 'A' for 'typedef struct _a { } A, D;'
+ debugPrintln(" - alias.20 -> "+getDebugTypeString(t));
+ } else if( null != tg && tg.isCompound() ) {
+ // This aliases 'B' -> 'A' for 'typedef A B;', where A is pointer to compound
+ debugPrintln(" - alias.21 -> "+getDebugTypeString(t));
+ } else {
+ // copy to preserve canonicalized base type
+ t = t.clone(locusTag);
+ t.setTypedefName(declName);
+ debugPrintln(" - copy.22 -> "+getDebugTypeString(t));
+ }
+ }
+*/
;
pointerGroup[TypeBox tb] { int x = 0; int y = 0; }
@@ -731,7 +957,8 @@ pointerGroup[TypeBox tb] { int x = 0; int y = 0; }
if (tb != null) {
tb.setType(canonicalize(new PointerType(SizeThunk.POINTER,
tb.type(),
- attrs2CVAttrs(x))));
+ attrs2CVAttrs(x),
+ findASTLocusTag(pointerGroup_AST_in))));
}
}
)+ )
@@ -756,7 +983,9 @@ typeName {
/* FIXME: the handling of types in this rule has not been well thought
out and is known to be incomplete. Currently it is only used to handle
pointerGroups for unnamed parameters. */
-nonemptyAbstractDeclarator[TypeBox tb]
+nonemptyAbstractDeclarator[TypeBox tb] {
+ final ASTLocusTag locusTag = findASTLocusTag(nonemptyAbstractDeclarator_AST_in);
+}
: #( NNonemptyAbstractDeclarator
( pointerGroup[tb]
( (LPAREN
@@ -764,7 +993,7 @@ nonemptyAbstractDeclarator[TypeBox tb]
| parameterTypeList
)?
RPAREN)
- | (LBRACKET (e1:expr)? RBRACKET) { handleArrayExpr(tb, e1); }
+ | (LBRACKET (e1:expr)? RBRACKET) { handleArrayExpr(tb, e1, locusTag); }
)*
| ( (LPAREN
@@ -772,7 +1001,7 @@ nonemptyAbstractDeclarator[TypeBox tb]
| parameterTypeList
)?
RPAREN)
- | (LBRACKET (e2:expr)? RBRACKET) { handleArrayExpr(tb, e2); }
+ | (LBRACKET (e2:expr)? RBRACKET) { handleArrayExpr(tb, e2, locusTag); }
)+
)
)
@@ -786,13 +1015,17 @@ intConstExpr returns [int i] { i = -1; }
final String enumName = e.getText();
final EnumType enumType = enumHash.get(enumName);
if( null == enumType ) {
- throw new IllegalArgumentException("Error: intConstExpr ID "+enumName+" recognized, but no containing enum-type found");
+ throwGlueGenException(intConstExpr_AST_in,
+ "Error: intConstExpr ID "+enumName+" recognized, but no containing enum-type found");
}
- final long enumValue = enumType.getEnumValue(enumName);
- System.err.println("INFO: intConstExpr: enum[Type "+enumType.getName()+", name "+enumName+", value "+enumValue+"]");
- if( (long)Integer.MIN_VALUE > enumValue || (long)Integer.MAX_VALUE < enumValue ) {
- throw new IndexOutOfBoundsException("Error: intConstExpr ID "+enumName+" enum-value "+enumValue+" out of int range");
+ final Enumerator enumerator = enumType.getEnum(enumName);
+ final CNumber number = enumerator.getNumber();
+ if( null != number && number.isInteger && !number.isLong ) {
+ debugPrintln("INFO: intConstExpr: enum[Type "+enumType.getName()+", "+enumerator+"]");
+ } else {
+ throwGlueGenException(intConstExpr_AST_in,
+ "Error: intConstExpr ID "+enumName+" enum "+enumerator+" not an int32_t");
}
- return (int)enumValue;
+ return (int)number.i;
}
;
diff --git a/src/antlr/com/jogamp/gluegen/cgram/StdCParser.g b/src/antlr/com/jogamp/gluegen/cgram/StdCParser.g
index 7b34656..26da996 100644
--- a/src/antlr/com/jogamp/gluegen/cgram/StdCParser.g
+++ b/src/antlr/com/jogamp/gluegen/cgram/StdCParser.g
@@ -1131,11 +1131,12 @@ options {
nw:NonWhitespace
("\r\n" | "\r" | "\n") ) {
if (n != null) {
- //System.out.println("addDefine: #define " + i.getText() + " " + n.getText());
+ // System.out.println("addDefine: #define " + i.getText() + " " + n.getText()+" @ "+lineObject.getSource()+":"+(lineObject.line+deferredLineCount));
addDefine(i.getText(), n.getText());
} else {
setPreprocessingDirective("#define " + i.getText() + " " + nw.getText());
}
+ deferredNewline();
}
| (~'\n')* { setPreprocessingDirective(getText()); }
)
@@ -1165,15 +1166,19 @@ protected LineDirective
}
:
{
- lineObject = new LineObject();
- deferredLineCount = 0;
+ lineObject = new LineObject();
+ deferredLineCount = 0;
}
("line")? //this would be for if the directive started "#line", but not there for GNU directives
(Space)+
- n:Number { lineObject.setLine(Integer.parseInt(n.getText())); }
+ n:Number {
+ lineObject.setLine(Integer.parseInt(n.getText()));
+ }
(Space)+
( fn:StringLiteral { try {
- lineObject.setSource(fn.getText().substring(1,fn.getText().length()-1));
+ final String newSource = fn.getText().substring(1,fn.getText().length()-1);
+ // System.out.println("line: "+lineObject.getSource()+" -> "+newSource+", line "+(lineObject.line+deferredLineCount));
+ lineObject.setSource(newSource);
}
catch (StringIndexOutOfBoundsException e) { /*not possible*/ }
}
diff --git a/src/antlr/com/jogamp/gluegen/jgram/JavaParser.g b/src/antlr/com/jogamp/gluegen/jgram/JavaParser.g
index f67579e..1c06bfd 100644
--- a/src/antlr/com/jogamp/gluegen/jgram/JavaParser.g
+++ b/src/antlr/com/jogamp/gluegen/jgram/JavaParser.g
@@ -8,105 +8,105 @@
* Run 'java Main <directory full of java files>'
*
* Contributing authors:
- * John Mitchell [email protected]
- * Terence Parr [email protected]
- * John Lilley [email protected]
- * Scott Stanchfield [email protected]
- * Markus Mohnen [email protected]
+ * John Mitchell [email protected]
+ * Terence Parr [email protected]
+ * John Lilley [email protected]
+ * Scott Stanchfield [email protected]
+ * Markus Mohnen [email protected]
* Peter Williams [email protected]
* Allan Jacobs [email protected]
* Steve Messick [email protected]
- * John Pybus [email protected]
+ * John Pybus [email protected]
*
* Version 1.00 December 9, 1997 -- initial release
* Version 1.01 December 10, 1997
- * fixed bug in octal def (0..7 not 0..8)
+ * fixed bug in octal def (0..7 not 0..8)
* Version 1.10 August 1998 (parrt)
- * added tree construction
- * fixed definition of WS,comments for mac,pc,unix newlines
- * added unary plus
+ * added tree construction
+ * fixed definition of WS,comments for mac,pc,unix newlines
+ * added unary plus
* Version 1.11 (Nov 20, 1998)
- * Added "shutup" option to turn off last ambig warning.
- * Fixed inner class def to allow named class defs as statements
- * synchronized requires compound not simple statement
- * add [] after builtInType DOT class in primaryExpression
- * "const" is reserved but not valid..removed from modifiers
+ * Added "shutup" option to turn off last ambig warning.
+ * Fixed inner class def to allow named class defs as statements
+ * synchronized requires compound not simple statement
+ * add [] after builtInType DOT class in primaryExpression
+ * "const" is reserved but not valid..removed from modifiers
* Version 1.12 (Feb 2, 1999)
- * Changed LITERAL_xxx to xxx in tree grammar.
- * Updated java.g to use tokens {...} now for 2.6.0 (new feature).
+ * Changed LITERAL_xxx to xxx in tree grammar.
+ * Updated java.g to use tokens {...} now for 2.6.0 (new feature).
*
* Version 1.13 (Apr 23, 1999)
- * Didn't have (stat)? for else clause in tree parser.
- * Didn't gen ASTs for interface extends. Updated tree parser too.
- * Updated to 2.6.0.
+ * Didn't have (stat)? for else clause in tree parser.
+ * Didn't gen ASTs for interface extends. Updated tree parser too.
+ * Updated to 2.6.0.
* Version 1.14 (Jun 20, 1999)
- * Allowed final/abstract on local classes.
- * Removed local interfaces from methods
- * Put instanceof precedence where it belongs...in relationalExpr
- * It also had expr not type as arg; fixed it.
- * Missing ! on SEMI in classBlock
- * fixed: (expr) + "string" was parsed incorrectly (+ as unary plus).
- * fixed: didn't like Object[].class in parser or tree parser
+ * Allowed final/abstract on local classes.
+ * Removed local interfaces from methods
+ * Put instanceof precedence where it belongs...in relationalExpr
+ * It also had expr not type as arg; fixed it.
+ * Missing ! on SEMI in classBlock
+ * fixed: (expr) + "string" was parsed incorrectly (+ as unary plus).
+ * fixed: didn't like Object[].class in parser or tree parser
* Version 1.15 (Jun 26, 1999)
- * Screwed up rule with instanceof in it. :( Fixed.
- * Tree parser didn't like (expr).something; fixed.
- * Allowed multiple inheritance in tree grammar. oops.
+ * Screwed up rule with instanceof in it. :( Fixed.
+ * Tree parser didn't like (expr).something; fixed.
+ * Allowed multiple inheritance in tree grammar. oops.
* Version 1.16 (August 22, 1999)
- * Extending an interface built a wacky tree: had extra EXTENDS.
- * Tree grammar didn't allow multiple superinterfaces.
- * Tree grammar didn't allow empty var initializer: {}
+ * Extending an interface built a wacky tree: had extra EXTENDS.
+ * Tree grammar didn't allow multiple superinterfaces.
+ * Tree grammar didn't allow empty var initializer: {}
* Version 1.17 (October 12, 1999)
- * ESC lexer rule allowed 399 max not 377 max.
- * java.tree.g didn't handle the expression of synchronized
- * statements.
+ * ESC lexer rule allowed 399 max not 377 max.
+ * java.tree.g didn't handle the expression of synchronized
+ * statements.
* Version 1.18 (August 12, 2001)
- * Terence updated to Java 2 Version 1.3 by
- * observing/combining work of Allan Jacobs and Steve
- * Messick. Handles 1.3 src. Summary:
- * o primary didn't include boolean.class kind of thing
- * o constructor calls parsed explicitly now:
- * see explicitConstructorInvocation
- * o add strictfp modifier
- * o missing objBlock after new expression in tree grammar
- * o merged local class definition alternatives, moved after declaration
- * o fixed problem with ClassName.super.field
- * o reordered some alternatives to make things more efficient
- * o long and double constants were not differentiated from int/float
- * o whitespace rule was inefficient: matched only one char
- * o add an examples directory with some nasty 1.3 cases
- * o made Main.java use buffered IO and a Reader for Unicode support
- * o supports UNICODE?
- * Using Unicode charVocabulay makes code file big, but only
- * in the bitsets at the end. I need to make ANTLR generate
- * unicode bitsets more efficiently.
+ * Terence updated to Java 2 Version 1.3 by
+ * observing/combining work of Allan Jacobs and Steve
+ * Messick. Handles 1.3 src. Summary:
+ * o primary didn't include boolean.class kind of thing
+ * o constructor calls parsed explicitly now:
+ * see explicitConstructorInvocation
+ * o add strictfp modifier
+ * o missing objBlock after new expression in tree grammar
+ * o merged local class definition alternatives, moved after declaration
+ * o fixed problem with ClassName.super.field
+ * o reordered some alternatives to make things more efficient
+ * o long and double constants were not differentiated from int/float
+ * o whitespace rule was inefficient: matched only one char
+ * o add an examples directory with some nasty 1.3 cases
+ * o made Main.java use buffered IO and a Reader for Unicode support
+ * o supports UNICODE?
+ * Using Unicode charVocabulay makes code file big, but only
+ * in the bitsets at the end. I need to make ANTLR generate
+ * unicode bitsets more efficiently.
* Version 1.19 (April 25, 2002)
- * Terence added in nice fixes by John Pybus concerning floating
- * constants and problems with super() calls. John did a nice
- * reorg of the primary/postfix expression stuff to read better
- * and makes f.g.super() parse properly (it was METHOD_CALL not
- * a SUPER_CTOR_CALL). Also:
+ * Terence added in nice fixes by John Pybus concerning floating
+ * constants and problems with super() calls. John did a nice
+ * reorg of the primary/postfix expression stuff to read better
+ * and makes f.g.super() parse properly (it was METHOD_CALL not
+ * a SUPER_CTOR_CALL). Also:
*
- * o "finally" clause was a root...made it a child of "try"
- * o Added stuff for asserts too for Java 1.4, but *commented out*
- * as it is not backward compatible.
+ * o "finally" clause was a root...made it a child of "try"
+ * o Added stuff for asserts too for Java 1.4, but *commented out*
+ * as it is not backward compatible.
*
* Version 1.20 (October 27, 2002)
*
* Terence ended up reorging John Pybus' stuff to
* remove some nondeterminisms and some syntactic predicates.
* Note that the grammar is stricter now; e.g., this(...) must
- * be the first statement.
+ * be the first statement.
*
* Trinary ?: operator wasn't working as array name:
* (isBig ? bigDigits : digits)[i];
*
* Checked parser/tree parser on source for
* Resin-2.0.5, jive-2.1.1, jdk 1.3.1, Lucene, antlr 2.7.2a4,
- * and the 110k-line jGuru server source.
+ * and the 110k-line jGuru server source.
*
* Version 1.21 (October 17, 2003)
- * Fixed lots of problems including:
- * Ray Waldin: add typeDefinition to interfaceBlock in java.tree.g
+ * Fixed lots of problems including:
+ * Ray Waldin: add typeDefinition to interfaceBlock in java.tree.g
* He found a problem/fix with floating point that start with 0
* Ray also fixed problem that (int.class) was not recognized.
* Thorsten van Ellen noticed that \n are allowed incorrectly in strings.
@@ -129,24 +129,24 @@ header {
class JavaParser extends Parser;
options {
- k = 2; // two token lookahead
- exportVocab=Java; // Call its vocabulary "Java"
- codeGenMakeSwitchThreshold = 2; // Some optimizations
- codeGenBitsetTestThreshold = 3;
- defaultErrorHandler = false; // Don't generate parser error handlers
- buildAST = true;
- //buildAST = false;
+ k = 2; // two token lookahead
+ exportVocab=Java; // Call its vocabulary "Java"
+ codeGenMakeSwitchThreshold = 2; // Some optimizations
+ codeGenBitsetTestThreshold = 3;
+ defaultErrorHandler = false; // Don't generate parser error handlers
+ buildAST = true;
+ //buildAST = false;
}
tokens {
- BLOCK; MODIFIERS; OBJBLOCK; SLIST; CTOR_DEF; METHOD_DEF; VARIABLE_DEF;
- INSTANCE_INIT; STATIC_INIT; TYPE; CLASS_DEF; INTERFACE_DEF;
- PACKAGE_DEF; ARRAY_DECLARATOR; EXTENDS_CLAUSE; IMPLEMENTS_CLAUSE;
- PARAMETERS; PARAMETER_DEF; LABELED_STAT; TYPECAST; INDEX_OP;
- POST_INC; POST_DEC; METHOD_CALL; EXPR; ARRAY_INIT;
- IMPORT; UNARY_MINUS; UNARY_PLUS; CASE_GROUP; ELIST; FOR_INIT; FOR_CONDITION;
- FOR_ITERATOR; EMPTY_STAT; FINAL="final"; ABSTRACT="abstract";
- STRICTFP="strictfp"; SUPER_CTOR_CALL; CTOR_CALL;
+ BLOCK; MODIFIERS; OBJBLOCK; SLIST; CTOR_DEF; METHOD_DEF; VARIABLE_DEF;
+ INSTANCE_INIT; STATIC_INIT; TYPE; CLASS_DEF; INTERFACE_DEF;
+ PACKAGE_DEF; ARRAY_DECLARATOR; EXTENDS_CLAUSE; IMPLEMENTS_CLAUSE;
+ PARAMETERS; PARAMETER_DEF; LABELED_STAT; TYPECAST; INDEX_OP;
+ POST_INC; POST_DEC; METHOD_CALL; EXPR; ARRAY_INIT;
+ IMPORT; UNARY_MINUS; UNARY_PLUS; CASE_GROUP; ELIST; FOR_INIT; FOR_CONDITION;
+ FOR_ITERATOR; EMPTY_STAT; FINAL="final"; ABSTRACT="abstract";
+ STRICTFP="strictfp"; SUPER_CTOR_CALL; CTOR_CALL;
}
{
@@ -181,250 +181,250 @@ tokens {
// Compilation Unit: In Java, this is a single file. This is the start
// rule for this parser
compilationUnit
- : // A compilation unit starts with an optional package definition
- ( packageDefinition
- | /* nothing */
- )
+ : // A compilation unit starts with an optional package definition
+ ( packageDefinition
+ | /* nothing */
+ )
- // Next we have a series of zero or more import statements
- ( importDefinition )*
+ // Next we have a series of zero or more import statements
+ ( importDefinition )*
- // Wrapping things up with any number of class or interface
- // definitions
- ( typeDefinition )*
+ // Wrapping things up with any number of class or interface
+ // definitions
+ ( typeDefinition )*
- EOF!
- ;
+ EOF!
+ ;
// Package statement: "package" followed by an identifier.
packageDefinition
- options {defaultErrorHandler = true;} // let ANTLR handle errors
- : p:"package"^ {#p.setType(PACKAGE_DEF);} identifier SEMI!
- ;
+ options {defaultErrorHandler = true;} // let ANTLR handle errors
+ : p:"package"^ {#p.setType(PACKAGE_DEF);} identifier SEMI!
+ ;
// Import statement: import followed by a package or class name
importDefinition
- options {defaultErrorHandler = true;}
- : i:"import"^ {#i.setType(IMPORT);} identifierStar SEMI!
- ;
+ options {defaultErrorHandler = true;}
+ : i:"import"^ {#i.setType(IMPORT);} identifierStar SEMI!
+ ;
// A type definition in a file is either a class or interface definition.
typeDefinition
- options {defaultErrorHandler = true;}
- : m:modifiers!
- ( classDefinition[#m]
- | interfaceDefinition[#m]
- )
- | SEMI!
- ;
+ options {defaultErrorHandler = true;}
+ : m:modifiers!
+ ( classDefinition[#m]
+ | interfaceDefinition[#m]
+ )
+ | SEMI!
+ ;
/** A declaration is the creation of a reference or primitive-type variable
* Create a separate Type/Var tree for each var in the var list.
*/
declaration!
- : m:modifiers t:typeSpec[false] v:variableDefinitions[#m,#t]
- {#declaration = #v;}
- ;
+ : m:modifiers t:typeSpec[false] v:variableDefinitions[#m,#t]
+ {#declaration = #v;}
+ ;
// A type specification is a type name with possible brackets afterwards
// (which would make it an array type).
typeSpec[boolean addImagNode]
- : classTypeSpec[addImagNode]
- | builtInTypeSpec[addImagNode]
- ;
+ : classTypeSpec[addImagNode]
+ | builtInTypeSpec[addImagNode]
+ ;
// A class type specification is a class type with possible brackets afterwards
// (which would make it an array type).
classTypeSpec[boolean addImagNode]
- : identifier (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
- {
- if ( addImagNode ) {
- #classTypeSpec = #(#[TYPE,"TYPE"], #classTypeSpec);
- }
- }
- ;
+ : identifier (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
+ {
+ if ( addImagNode ) {
+ #classTypeSpec = #(#[TYPE,"TYPE"], #classTypeSpec);
+ }
+ }
+ ;
// A builtin type specification is a builtin type with possible brackets
// afterwards (which would make it an array type).
builtInTypeSpec[boolean addImagNode]
- : builtInType (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
- {
- if ( addImagNode ) {
- #builtInTypeSpec = #(#[TYPE,"TYPE"], #builtInTypeSpec);
- }
- }
- ;
+ : builtInType (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
+ {
+ if ( addImagNode ) {
+ #builtInTypeSpec = #(#[TYPE,"TYPE"], #builtInTypeSpec);
+ }
+ }
+ ;
// A type name. which is either a (possibly qualified) class name or
// a primitive (builtin) type
type
- : identifier
- | builtInType
- ;
+ : identifier
+ | builtInType
+ ;
// The primitive types.
builtInType
- : "void"
- | "boolean"
- | "byte"
- | "char"
- | "short"
- | "int"
- | "float"
- | "long"
- | "double"
- ;
+ : "void"
+ | "boolean"
+ | "byte"
+ | "char"
+ | "short"
+ | "int"
+ | "float"
+ | "long"
+ | "double"
+ ;
// A (possibly-qualified) java identifier. We start with the first IDENT
// and expand its name by adding dots and following IDENTS
identifier
- : IDENT ( DOT^ IDENT )*
- ;
+ : IDENT ( DOT^ IDENT )*
+ ;
identifierStar
- : IDENT
- ( DOT^ IDENT )*
- ( DOT^ STAR )?
- ;
+ : IDENT
+ ( DOT^ IDENT )*
+ ( DOT^ STAR )?
+ ;
// A list of zero or more modifiers. We could have used (modifier)* in
// place of a call to modifiers, but I thought it was a good idea to keep
// this rule separate so they can easily be collected in a Vector if
// someone so desires
modifiers
- : ( modifier )*
- {#modifiers = #([MODIFIERS, "MODIFIERS"], #modifiers);}
- ;
+ : ( modifier )*
+ {#modifiers = #([MODIFIERS, "MODIFIERS"], #modifiers);}
+ ;
// modifiers for Java classes, interfaces, class/instance vars and methods
modifier
- : "private"
- | "public"
- | "protected"
- | "static"
- | "transient"
- | "final"
- | "abstract"
- | "native"
- | "threadsafe"
- | "synchronized"
-// | "const" // reserved word, but not valid
- | "volatile"
- | "strictfp"
- ;
+ : "private"
+ | "public"
+ | "protected"
+ | "static"
+ | "transient"
+ | "final"
+ | "abstract"
+ | "native"
+ | "threadsafe"
+ | "synchronized"
+// | "const" // reserved word, but not valid
+ | "volatile"
+ | "strictfp"
+ ;
// Definition of a Java class
classDefinition![AST modifiers]
- : "class" IDENT
- // it _might_ have a superclass...
- sc:superClassClause
- // it might implement some interfaces...
- ic:implementsClause
- // now parse the body of the class
- cb:classBlock
- {#classDefinition = #(#[CLASS_DEF,"CLASS_DEF"],
- modifiers,IDENT,sc,ic,cb);}
- ;
+ : "class" IDENT
+ // it _might_ have a superclass...
+ sc:superClassClause
+ // it might implement some interfaces...
+ ic:implementsClause
+ // now parse the body of the class
+ cb:classBlock
+ {#classDefinition = #(#[CLASS_DEF,"CLASS_DEF"],
+ modifiers,IDENT,sc,ic,cb);}
+ ;
superClassClause!
- : ( "extends" id:identifier )?
- {#superClassClause = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],id);}
- ;
+ : ( "extends" id:identifier )?
+ {#superClassClause = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],id);}
+ ;
// Definition of a Java Interface
interfaceDefinition![AST modifiers]
- : "interface" IDENT
- // it might extend some other interfaces
- ie:interfaceExtends
- // now parse the body of the interface (looks like a class...)
- cb:classBlock
- {#interfaceDefinition = #(#[INTERFACE_DEF,"INTERFACE_DEF"],
- modifiers,IDENT,ie,cb);}
- ;
+ : "interface" IDENT
+ // it might extend some other interfaces
+ ie:interfaceExtends
+ // now parse the body of the interface (looks like a class...)
+ cb:classBlock
+ {#interfaceDefinition = #(#[INTERFACE_DEF,"INTERFACE_DEF"],
+ modifiers,IDENT,ie,cb);}
+ ;
// This is the body of a class. You can have fields and extra semicolons,
// That's about it (until you see what a field is...)
classBlock
- : LCURLY! { blockDepth++; }
- ( field | SEMI! )*
- RCURLY! { blockDepth--; }
- {#classBlock = #([OBJBLOCK, "OBJBLOCK"], #classBlock);}
- ;
+ : LCURLY! { blockDepth++; }
+ ( field | SEMI! )*
+ RCURLY! { blockDepth--; }
+ {#classBlock = #([OBJBLOCK, "OBJBLOCK"], #classBlock);}
+ ;
// An interface can extend several other interfaces...
interfaceExtends
- : (
- e:"extends"!
- identifier ( COMMA! identifier )*
- )?
- {#interfaceExtends = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],
- #interfaceExtends);}
- ;
+ : (
+ e:"extends"!
+ identifier ( COMMA! identifier )*
+ )?
+ {#interfaceExtends = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],
+ #interfaceExtends);}
+ ;
// A class can implement several interfaces...
implementsClause
- : (
- i:"implements"! identifier ( COMMA! identifier )*
- )?
- {#implementsClause = #(#[IMPLEMENTS_CLAUSE,"IMPLEMENTS_CLAUSE"],
- #implementsClause);}
- ;
+ : (
+ i:"implements"! identifier ( COMMA! identifier )*
+ )?
+ {#implementsClause = #(#[IMPLEMENTS_CLAUSE,"IMPLEMENTS_CLAUSE"],
+ #implementsClause);}
+ ;
// Now the various things that can be defined inside a class or interface...
// Note that not all of these are really valid in an interface (constructors,
// for example), and if this grammar were used for a compiler there would
// need to be some semantic checks to make sure we're doing the right thing...
field!
- : // method, constructor, or variable declaration
- mods:modifiers
- ( h:ctorHead s:constructorBody // constructor
- {#field = #(#[CTOR_DEF,"CTOR_DEF"], mods, h, s);}
+ : // method, constructor, or variable declaration
+ mods:modifiers
+ ( h:ctorHead s:constructorBody // constructor
+ {#field = #(#[CTOR_DEF,"CTOR_DEF"], mods, h, s);}
- | cd:classDefinition[#mods] // inner class
- {#field = #cd;}
+ | cd:classDefinition[#mods] // inner class
+ {#field = #cd;}
- | id:interfaceDefinition[#mods] // inner interface
- {#field = #id;}
+ | id:interfaceDefinition[#mods] // inner interface
+ {#field = #id;}
- | t:typeSpec[false] // method or variable declaration(s)
- ( fn:IDENT // the name of the method
+ | t:typeSpec[false] // method or variable declaration(s)
+ ( fn:IDENT // the name of the method
- // parse the formal parameter declarations.
- LPAREN! param:parameterDeclarationList RPAREN!
+ // parse the formal parameter declarations.
+ LPAREN! param:parameterDeclarationList RPAREN!
- rt:declaratorBrackets[#t]
+ rt:declaratorBrackets[#t]
- // get the list of exceptions that this method is
- // declared to throw
- (tc:throwsClause)?
+ // get the list of exceptions that this method is
+ // declared to throw
+ (tc:throwsClause)?
- ( s2:compoundStatement | SEMI )
- {#field = #(#[METHOD_DEF,"METHOD_DEF"],
- mods,
- #(#[TYPE,"TYPE"],rt),
- fn,
- param,
- tc,
- s2);
+ ( s2:compoundStatement | SEMI )
+ {#field = #(#[METHOD_DEF,"METHOD_DEF"],
+ mods,
+ #(#[TYPE,"TYPE"],rt),
+ fn,
+ param,
+ tc,
+ s2);
if(blockDepth==1) {
functionNames.add(fn.getText()); } }
- | v:variableDefinitions[#mods,#t] SEMI
-// {#field = #(#[VARIABLE_DEF,"VARIABLE_DEF"], v);}
- {#field = #v;}
- )
- )
+ | v:variableDefinitions[#mods,#t] SEMI
+// {#field = #(#[VARIABLE_DEF,"VARIABLE_DEF"], v);}
+ {#field = #v;}
+ )
+ )
// "static { ... }" class initializer
- | "static" s3:compoundStatement
- {#field = #(#[STATIC_INIT,"STATIC_INIT"], s3);}
+ | "static" s3:compoundStatement
+ {#field = #(#[STATIC_INIT,"STATIC_INIT"], s3);}
// "{ ... }" instance initializer
- | s4:compoundStatement
- {#field = #(#[INSTANCE_INIT,"INSTANCE_INIT"], s4);}
- ;
+ | s4:compoundStatement
+ {#field = #(#[INSTANCE_INIT,"INSTANCE_INIT"], s4);}
+ ;
constructorBody
: lc:LCURLY^ {#lc.setType(SLIST); blockDepth++; }
@@ -436,108 +436,108 @@ constructorBody
/** Catch obvious constructor calls, but not the expr.super(...) calls */
explicitConstructorInvocation
: "this"! lp1:LPAREN^ argList RPAREN! SEMI!
- {#lp1.setType(CTOR_CALL);}
+ {#lp1.setType(CTOR_CALL);}
| "super"! lp2:LPAREN^ argList RPAREN! SEMI!
- {#lp2.setType(SUPER_CTOR_CALL);}
+ {#lp2.setType(SUPER_CTOR_CALL);}
;
variableDefinitions[AST mods, AST t]
- : variableDeclarator[getASTFactory().dupTree(mods),
- getASTFactory().dupTree(t)]
- ( COMMA!
- variableDeclarator[getASTFactory().dupTree(mods),
- getASTFactory().dupTree(t)]
- )*
- ;
+ : variableDeclarator[getASTFactory().dupTree(mods),
+ getASTFactory().dupTree(t)]
+ ( COMMA!
+ variableDeclarator[getASTFactory().dupTree(mods),
+ getASTFactory().dupTree(t)]
+ )*
+ ;
/** Declaration of a variable. This can be a class/instance variable,
* or a local variable in a method
* It can also include possible initialization.
*/
variableDeclarator![AST mods, AST t]
- : id:IDENT d:declaratorBrackets[t] v:varInitializer
- {#variableDeclarator = #(#[VARIABLE_DEF,"VARIABLE_DEF"], mods, #(#[TYPE,"TYPE"],d), id, v);
+ : id:IDENT d:declaratorBrackets[t] v:varInitializer
+ {#variableDeclarator = #(#[VARIABLE_DEF,"VARIABLE_DEF"], mods, #(#[TYPE,"TYPE"],d), id, v);
if(blockDepth==1) {
enumNames.add(id.getText());
}
}
- ;
+ ;
declaratorBrackets[AST typ]
- : {#declaratorBrackets=typ;}
- (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
- ;
+ : {#declaratorBrackets=typ;}
+ (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
+ ;
varInitializer
- : ( ASSIGN^ initializer )?
- ;
+ : ( ASSIGN^ initializer )?
+ ;
// This is an initializer used to set up an array.
arrayInitializer
- : lc:LCURLY^ {#lc.setType(ARRAY_INIT); blockDepth++; }
- ( initializer
- (
- // CONFLICT: does a COMMA after an initializer start a new
- // initializer or start the option ',' at end?
- // ANTLR generates proper code by matching
- // the comma as soon as possible.
- options {
- warnWhenFollowAmbig = false;
- }
- :
- COMMA! initializer
- )*
- (COMMA!)?
- )?
- RCURLY! { blockDepth--; }
- ;
+ : lc:LCURLY^ {#lc.setType(ARRAY_INIT); blockDepth++; }
+ ( initializer
+ (
+ // CONFLICT: does a COMMA after an initializer start a new
+ // initializer or start the option ',' at end?
+ // ANTLR generates proper code by matching
+ // the comma as soon as possible.
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ :
+ COMMA! initializer
+ )*
+ (COMMA!)?
+ )?
+ RCURLY! { blockDepth--; }
+ ;
// The two "things" that can initialize an array element are an expression
// and another (nested) array initializer.
initializer
- : expression
- | arrayInitializer
- ;
+ : expression
+ | arrayInitializer
+ ;
// This is the header of a method. It includes the name and parameters
// for the method.
// This also watches for a list of exception classes in a "throws" clause.
ctorHead
- : IDENT // the name of the method
+ : IDENT // the name of the method
- // parse the formal parameter declarations.
- LPAREN! parameterDeclarationList RPAREN!
+ // parse the formal parameter declarations.
+ LPAREN! parameterDeclarationList RPAREN!
- // get the list of exceptions that this method is declared to throw
- (throwsClause)?
- ;
+ // get the list of exceptions that this method is declared to throw
+ (throwsClause)?
+ ;
// This is a list of exception classes that the method is declared to throw
throwsClause
- : "throws"^ identifier ( COMMA! identifier )*
- ;
+ : "throws"^ identifier ( COMMA! identifier )*
+ ;
// A list of formal parameters
parameterDeclarationList
- : ( parameterDeclaration ( COMMA! parameterDeclaration )* )?
- {#parameterDeclarationList = #(#[PARAMETERS,"PARAMETERS"],
- #parameterDeclarationList);}
- ;
+ : ( parameterDeclaration ( COMMA! parameterDeclaration )* )?
+ {#parameterDeclarationList = #(#[PARAMETERS,"PARAMETERS"],
+ #parameterDeclarationList);}
+ ;
// A formal parameter.
parameterDeclaration!
- : pm:parameterModifier t:typeSpec[false] id:IDENT
- pd:declaratorBrackets[#t]
- {#parameterDeclaration = #(#[PARAMETER_DEF,"PARAMETER_DEF"],
- pm, #([TYPE,"TYPE"],pd), id);}
- ;
+ : pm:parameterModifier t:typeSpec[false] id:IDENT
+ pd:declaratorBrackets[#t]
+ {#parameterDeclaration = #(#[PARAMETER_DEF,"PARAMETER_DEF"],
+ pm, #([TYPE,"TYPE"],pd), id);}
+ ;
parameterModifier
- : (f:"final")?
- {#parameterModifier = #(#[MODIFIERS,"MODIFIERS"], f);}
- ;
+ : (f:"final")?
+ {#parameterModifier = #(#[MODIFIERS,"MODIFIERS"], f);}
+ ;
// Compound statement. This is used in many contexts:
// Inside a class definition prefixed with "static":
@@ -549,151 +549,151 @@ parameterModifier
// it starts a new scope for variable definitions
compoundStatement
- : lc:LCURLY^ {#lc.setType(SLIST); blockDepth++; }
- // include the (possibly-empty) list of statements
- (statement)*
- RCURLY! { blockDepth--; }
- ;
+ : lc:LCURLY^ {#lc.setType(SLIST); blockDepth++; }
+ // include the (possibly-empty) list of statements
+ (statement)*
+ RCURLY! { blockDepth--; }
+ ;
statement
- // A list of statements in curly braces -- start a new scope!
- : compoundStatement
-
- // declarations are ambiguous with "ID DOT" relative to expression
- // statements. Must backtrack to be sure. Could use a semantic
- // predicate to test symbol table to see what the type was coming
- // up, but that's pretty hard without a symbol table ;)
- | (declaration)=> declaration SEMI!
-
- // An expression statement. This could be a method call,
- // assignment statement, or any other expression evaluated for
- // side-effects.
- | expression SEMI!
-
- // class definition
- | m:modifiers! classDefinition[#m]
-
- // Attach a label to the front of a statement
- | IDENT c:COLON^ {#c.setType(LABELED_STAT);} statement
-
- // If-else statement
- | "if"^ LPAREN! expression RPAREN! statement
- (
- // CONFLICT: the old "dangling-else" problem...
- // ANTLR generates proper code matching
- // as soon as possible. Hush warning.
- options {
- warnWhenFollowAmbig = false;
- }
- :
- "else"! statement
- )?
-
- // For statement
- | "for"^
- LPAREN!
- forInit SEMI! // initializer
- forCond SEMI! // condition test
- forIter // updater
- RPAREN!
- statement // statement to loop over
-
- // While statement
- | "while"^ LPAREN! expression RPAREN! statement
-
- // do-while statement
- | "do"^ statement "while"! LPAREN! expression RPAREN! SEMI!
-
- // get out of a loop (or switch)
- | "break"^ (IDENT)? SEMI!
-
- // do next iteration of a loop
- | "continue"^ (IDENT)? SEMI!
-
- // Return an expression
- | "return"^ (expression)? SEMI!
-
- // switch/case statement
- | "switch"^ LPAREN! expression RPAREN! LCURLY! { blockDepth++; }
- ( casesGroup )*
- RCURLY! { blockDepth--; }
-
- // exception try-catch block
- | tryBlock
-
- // throw an exception
- | "throw"^ expression SEMI!
-
- // synchronize a statement
- | "synchronized"^ LPAREN! expression RPAREN! compoundStatement
-
- // asserts (uncomment if you want 1.4 compatibility)
- // | "assert"^ expression ( COLON! expression )? SEMI!
-
- // empty statement
- | s:SEMI {#s.setType(EMPTY_STAT);}
- ;
+ // A list of statements in curly braces -- start a new scope!
+ : compoundStatement
+
+ // declarations are ambiguous with "ID DOT" relative to expression
+ // statements. Must backtrack to be sure. Could use a semantic
+ // predicate to test symbol table to see what the type was coming
+ // up, but that's pretty hard without a symbol table ;)
+ | (declaration)=> declaration SEMI!
+
+ // An expression statement. This could be a method call,
+ // assignment statement, or any other expression evaluated for
+ // side-effects.
+ | expression SEMI!
+
+ // class definition
+ | m:modifiers! classDefinition[#m]
+
+ // Attach a label to the front of a statement
+ | IDENT c:COLON^ {#c.setType(LABELED_STAT);} statement
+
+ // If-else statement
+ | "if"^ LPAREN! expression RPAREN! statement
+ (
+ // CONFLICT: the old "dangling-else" problem...
+ // ANTLR generates proper code matching
+ // as soon as possible. Hush warning.
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ :
+ "else"! statement
+ )?
+
+ // For statement
+ | "for"^
+ LPAREN!
+ forInit SEMI! // initializer
+ forCond SEMI! // condition test
+ forIter // updater
+ RPAREN!
+ statement // statement to loop over
+
+ // While statement
+ | "while"^ LPAREN! expression RPAREN! statement
+
+ // do-while statement
+ | "do"^ statement "while"! LPAREN! expression RPAREN! SEMI!
+
+ // get out of a loop (or switch)
+ | "break"^ (IDENT)? SEMI!
+
+ // do next iteration of a loop
+ | "continue"^ (IDENT)? SEMI!
+
+ // Return an expression
+ | "return"^ (expression)? SEMI!
+
+ // switch/case statement
+ | "switch"^ LPAREN! expression RPAREN! LCURLY! { blockDepth++; }
+ ( casesGroup )*
+ RCURLY! { blockDepth--; }
+
+ // exception try-catch block
+ | tryBlock
+
+ // throw an exception
+ | "throw"^ expression SEMI!
+
+ // synchronize a statement
+ | "synchronized"^ LPAREN! expression RPAREN! compoundStatement
+
+ // asserts (uncomment if you want 1.4 compatibility)
+ // | "assert"^ expression ( COLON! expression )? SEMI!
+
+ // empty statement
+ | s:SEMI {#s.setType(EMPTY_STAT);}
+ ;
casesGroup
- : ( // CONFLICT: to which case group do the statements bind?
- // ANTLR generates proper code: it groups the
- // many "case"/"default" labels together then
- // follows them with the statements
- options {
- greedy = true;
- }
- :
- aCase
- )+
- caseSList
- {#casesGroup = #([CASE_GROUP, "CASE_GROUP"], #casesGroup);}
- ;
+ : ( // CONFLICT: to which case group do the statements bind?
+ // ANTLR generates proper code: it groups the
+ // many "case"/"default" labels together then
+ // follows them with the statements
+ options {
+ greedy = true;
+ }
+ :
+ aCase
+ )+
+ caseSList
+ {#casesGroup = #([CASE_GROUP, "CASE_GROUP"], #casesGroup);}
+ ;
aCase
- : ("case"^ expression | "default") COLON!
- ;
+ : ("case"^ expression | "default") COLON!
+ ;
caseSList
- : (statement)*
- {#caseSList = #(#[SLIST,"SLIST"],#caseSList);}
- ;
+ : (statement)*
+ {#caseSList = #(#[SLIST,"SLIST"],#caseSList);}
+ ;
// The initializer for a for loop
forInit
- // if it looks like a declaration, it is
- : ( (declaration)=> declaration
- // otherwise it could be an expression list...
- | expressionList
- )?
- {#forInit = #(#[FOR_INIT,"FOR_INIT"],#forInit);}
- ;
+ // if it looks like a declaration, it is
+ : ( (declaration)=> declaration
+ // otherwise it could be an expression list...
+ | expressionList
+ )?
+ {#forInit = #(#[FOR_INIT,"FOR_INIT"],#forInit);}
+ ;
forCond
- : (expression)?
- {#forCond = #(#[FOR_CONDITION,"FOR_CONDITION"],#forCond);}
- ;
+ : (expression)?
+ {#forCond = #(#[FOR_CONDITION,"FOR_CONDITION"],#forCond);}
+ ;
forIter
- : (expressionList)?
- {#forIter = #(#[FOR_ITERATOR,"FOR_ITERATOR"],#forIter);}
- ;
+ : (expressionList)?
+ {#forIter = #(#[FOR_ITERATOR,"FOR_ITERATOR"],#forIter);}
+ ;
// an exception handler try/catch block
tryBlock
- : "try"^ compoundStatement
- (handler)*
- ( finallyClause )?
- ;
+ : "try"^ compoundStatement
+ (handler)*
+ ( finallyClause )?
+ ;
finallyClause
- : "finally"^ compoundStatement
- ;
+ : "finally"^ compoundStatement
+ ;
// an exception handler
handler
- : "catch"^ LPAREN! parameterDeclaration RPAREN! compoundStatement
- ;
+ : "catch"^ LPAREN! parameterDeclaration RPAREN! compoundStatement
+ ;
// expressions
@@ -732,22 +732,22 @@ handler
// the mother of all expressions
expression
- : assignmentExpression
- {#expression = #(#[EXPR,"EXPR"],#expression);}
- ;
+ : assignmentExpression
+ {#expression = #(#[EXPR,"EXPR"],#expression);}
+ ;
// This is a list of expressions.
expressionList
- : expression (COMMA! expression)*
- {#expressionList = #(#[ELIST,"ELIST"], expressionList);}
- ;
+ : expression (COMMA! expression)*
+ {#expressionList = #(#[ELIST,"ELIST"], expressionList);}
+ ;
// assignment expression (level 13)
assignmentExpression
- : conditionalExpression
- ( ( ASSIGN^
+ : conditionalExpression
+ ( ( ASSIGN^
| PLUS_ASSIGN^
| MINUS_ASSIGN^
| STAR_ASSIGN^
@@ -760,99 +760,99 @@ assignmentExpression
| BXOR_ASSIGN^
| BOR_ASSIGN^
)
- assignmentExpression
- )?
- ;
+ assignmentExpression
+ )?
+ ;
// conditional test (level 12)
conditionalExpression
- : logicalOrExpression
- ( QUESTION^ assignmentExpression COLON! conditionalExpression )?
- ;
+ : logicalOrExpression
+ ( QUESTION^ assignmentExpression COLON! conditionalExpression )?
+ ;
// logical or (||) (level 11)
logicalOrExpression
- : logicalAndExpression (LOR^ logicalAndExpression)*
- ;
+ : logicalAndExpression (LOR^ logicalAndExpression)*
+ ;
// logical and (&&) (level 10)
logicalAndExpression
- : inclusiveOrExpression (LAND^ inclusiveOrExpression)*
- ;
+ : inclusiveOrExpression (LAND^ inclusiveOrExpression)*
+ ;
// bitwise or non-short-circuiting or (|) (level 9)
inclusiveOrExpression
- : exclusiveOrExpression (BOR^ exclusiveOrExpression)*
- ;
+ : exclusiveOrExpression (BOR^ exclusiveOrExpression)*
+ ;
// exclusive or (^) (level 8)
exclusiveOrExpression
- : andExpression (BXOR^ andExpression)*
- ;
+ : andExpression (BXOR^ andExpression)*
+ ;
// bitwise or non-short-circuiting and (&) (level 7)
andExpression
- : equalityExpression (BAND^ equalityExpression)*
- ;
+ : equalityExpression (BAND^ equalityExpression)*
+ ;
// equality/inequality (==/!=) (level 6)
equalityExpression
- : relationalExpression ((NOT_EQUAL^ | EQUAL^) relationalExpression)*
- ;
+ : relationalExpression ((NOT_EQUAL^ | EQUAL^) relationalExpression)*
+ ;
// boolean relational expressions (level 5)
relationalExpression
- : shiftExpression
- ( ( ( LT^
- | GT^
- | LE^
- | GE^
- )
- shiftExpression
- )*
- | "instanceof"^ typeSpec[true]
- )
- ;
+ : shiftExpression
+ ( ( ( LT^
+ | GT^
+ | LE^
+ | GE^
+ )
+ shiftExpression
+ )*
+ | "instanceof"^ typeSpec[true]
+ )
+ ;
// bit shift expressions (level 4)
shiftExpression
- : additiveExpression ((SL^ | SR^ | BSR^) additiveExpression)*
- ;
+ : additiveExpression ((SL^ | SR^ | BSR^) additiveExpression)*
+ ;
// binary addition/subtraction (level 3)
additiveExpression
- : multiplicativeExpression ((PLUS^ | MINUS^) multiplicativeExpression)*
- ;
+ : multiplicativeExpression ((PLUS^ | MINUS^) multiplicativeExpression)*
+ ;
// multiplication/division/modulo (level 2)
multiplicativeExpression
- : unaryExpression ((STAR^ | DIV^ | MOD^ ) unaryExpression)*
- ;
+ : unaryExpression ((STAR^ | DIV^ | MOD^ ) unaryExpression)*
+ ;
unaryExpression
- : INC^ unaryExpression
- | DEC^ unaryExpression
- | MINUS^ {#MINUS.setType(UNARY_MINUS);} unaryExpression
- | PLUS^ {#PLUS.setType(UNARY_PLUS);} unaryExpression
- | unaryExpressionNotPlusMinus
- ;
+ : INC^ unaryExpression
+ | DEC^ unaryExpression
+ | MINUS^ {#MINUS.setType(UNARY_MINUS);} unaryExpression
+ | PLUS^ {#PLUS.setType(UNARY_PLUS);} unaryExpression
+ | unaryExpressionNotPlusMinus
+ ;
unaryExpressionNotPlusMinus
- : BNOT^ unaryExpression
- | LNOT^ unaryExpression
+ : BNOT^ unaryExpression
+ | LNOT^ unaryExpression
- // use predicate to skip cases like: (int.class)
+ // use predicate to skip cases like: (int.class)
| (LPAREN builtInTypeSpec[true] RPAREN) =>
lpb:LPAREN^ {#lpb.setType(TYPECAST);} builtInTypeSpec[true] RPAREN!
unaryExpression
@@ -860,108 +860,108 @@ unaryExpressionNotPlusMinus
// Have to backtrack to see if operator follows. If no operator
// follows, it's a typecast. No semantic checking needed to parse.
// if it _looks_ like a cast, it _is_ a cast; else it's a "(expr)"
- | (LPAREN classTypeSpec[true] RPAREN unaryExpressionNotPlusMinus)=>
+ | (LPAREN classTypeSpec[true] RPAREN unaryExpressionNotPlusMinus)=>
lp:LPAREN^ {#lp.setType(TYPECAST);} classTypeSpec[true] RPAREN!
unaryExpressionNotPlusMinus
- | postfixExpression
- ;
+ | postfixExpression
+ ;
// qualified names, array expressions, method invocation, post inc/dec
postfixExpression
- :
+ :
/*
"this"! lp1:LPAREN^ argList RPAREN!
- {#lp1.setType(CTOR_CALL);}
+ {#lp1.setType(CTOR_CALL);}
| "super"! lp2:LPAREN^ argList RPAREN!
- {#lp2.setType(SUPER_CTOR_CALL);}
+ {#lp2.setType(SUPER_CTOR_CALL);}
|
*/
primaryExpression
- (
+ (
/*
options {
- // the use of postfixExpression in SUPER_CTOR_CALL adds DOT
- // to the lookahead set, and gives loads of false non-det
- // warnings.
- // shut them off.
- generateAmbigWarnings=false;
- }
- : */
+ // the use of postfixExpression in SUPER_CTOR_CALL adds DOT
+ // to the lookahead set, and gives loads of false non-det
+ // warnings.
+ // shut them off.
+ generateAmbigWarnings=false;
+ }
+ : */
DOT^ IDENT
- ( lp:LPAREN^ {#lp.setType(METHOD_CALL);}
- argList
- RPAREN!
- )?
- | DOT^ "this"
+ ( lp:LPAREN^ {#lp.setType(METHOD_CALL);}
+ argList
+ RPAREN!
+ )?
+ | DOT^ "this"
- | DOT^ "super"
+ | DOT^ "super"
( // (new Outer()).super() (create enclosing instance)
lp3:LPAREN^ argList RPAREN!
{#lp3.setType(SUPER_CTOR_CALL);}
- | DOT^ IDENT
- ( lps:LPAREN^ {#lps.setType(METHOD_CALL);}
+ | DOT^ IDENT
+ ( lps:LPAREN^ {#lps.setType(METHOD_CALL);}
argList
RPAREN!
)?
)
- | DOT^ newExpression
- | lb:LBRACK^ {#lb.setType(INDEX_OP);} expression RBRACK!
- )*
+ | DOT^ newExpression
+ | lb:LBRACK^ {#lb.setType(INDEX_OP);} expression RBRACK!
+ )*
- ( // possibly add on a post-increment or post-decrement.
+ ( // possibly add on a post-increment or post-decrement.
// allows INC/DEC on too much, but semantics can check
- in:INC^ {#in.setType(POST_INC);}
- | de:DEC^ {#de.setType(POST_DEC);}
- )?
- ;
+ in:INC^ {#in.setType(POST_INC);}
+ | de:DEC^ {#de.setType(POST_DEC);}
+ )?
+ ;
// the basic element of an expression
primaryExpression
- : identPrimary ( options {greedy=true;} : DOT^ "class" )?
+ : identPrimary ( options {greedy=true;} : DOT^ "class" )?
| constant
- | "true"
- | "false"
- | "null"
+ | "true"
+ | "false"
+ | "null"
| newExpression
- | "this"
- | "super"
- | LPAREN! assignmentExpression RPAREN!
- // look for int.class and int[].class
- | builtInType
- ( lbt:LBRACK^ {#lbt.setType(ARRAY_DECLARATOR);} RBRACK! )*
- DOT^ "class"
- ;
+ | "this"
+ | "super"
+ | LPAREN! assignmentExpression RPAREN!
+ // look for int.class and int[].class
+ | builtInType
+ ( lbt:LBRACK^ {#lbt.setType(ARRAY_DECLARATOR);} RBRACK! )*
+ DOT^ "class"
+ ;
/** Match a, a.b.c refs, a.b.c(...) refs, a.b.c[], a.b.c[].class,
* and a.b.c.class refs. Also this(...) and super(...). Match
* this or super.
*/
identPrimary
- : IDENT
- (
+ : IDENT
+ (
options {
- // .ident could match here or in postfixExpression.
- // We do want to match here. Turn off warning.
- greedy=true;
- }
- : DOT^ IDENT
- )*
- (
+ // .ident could match here or in postfixExpression.
+ // We do want to match here. Turn off warning.
+ greedy=true;
+ }
+ : DOT^ IDENT
+ )*
+ (
options {
- // ARRAY_DECLARATOR here conflicts with INDEX_OP in
- // postfixExpression on LBRACK RBRACK.
- // We want to match [] here, so greedy. This overcomes
+ // ARRAY_DECLARATOR here conflicts with INDEX_OP in
+ // postfixExpression on LBRACK RBRACK.
+ // We want to match [] here, so greedy. This overcomes
// limitation of linear approximate lookahead.
- greedy=true;
- }
- : ( lp:LPAREN^ {#lp.setType(METHOD_CALL);} argList RPAREN! )
- | ( options {greedy=true;} :
+ greedy=true;
+ }
+ : ( lp:LPAREN^ {#lp.setType(METHOD_CALL);} argList RPAREN! )
+ | ( options {greedy=true;} :
lbc:LBRACK^ {#lbc.setType(ARRAY_DECLARATOR);} RBRACK!
)+
- )?
+ )?
;
/** object instantiation.
@@ -1014,53 +1014,53 @@ identPrimary
*
*/
newExpression
- : "new"^ type
- ( LPAREN! argList RPAREN! (classBlock)?
-
- //java 1.1
- // Note: This will allow bad constructs like
- // new int[4][][3] {exp,exp}.
- // There needs to be a semantic check here...
- // to make sure:
- // a) [ expr ] and [ ] are not mixed
- // b) [ expr ] and an init are not used together
-
- | newArrayDeclarator (arrayInitializer)?
- )
- ;
+ : "new"^ type
+ ( LPAREN! argList RPAREN! (classBlock)?
+
+ //java 1.1
+ // Note: This will allow bad constructs like
+ // new int[4][][3] {exp,exp}.
+ // There needs to be a semantic check here...
+ // to make sure:
+ // a) [ expr ] and [ ] are not mixed
+ // b) [ expr ] and an init are not used together
+
+ | newArrayDeclarator (arrayInitializer)?
+ )
+ ;
argList
- : ( expressionList
- | /*nothing*/
- {#argList = #[ELIST,"ELIST"];}
- )
- ;
+ : ( expressionList
+ | /*nothing*/
+ {#argList = #[ELIST,"ELIST"];}
+ )
+ ;
newArrayDeclarator
- : (
- // CONFLICT:
- // newExpression is a primaryExpression which can be
- // followed by an array index reference. This is ok,
- // as the generated code will stay in this loop as
- // long as it sees an LBRACK (proper behavior)
- options {
- warnWhenFollowAmbig = false;
- }
- :
- lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);}
- (expression)?
- RBRACK!
- )+
- ;
+ : (
+ // CONFLICT:
+ // newExpression is a primaryExpression which can be
+ // followed by an array index reference. This is ok,
+ // as the generated code will stay in this loop as
+ // long as it sees an LBRACK (proper behavior)
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ :
+ lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);}
+ (expression)?
+ RBRACK!
+ )+
+ ;
constant
- : NUM_INT
- | CHAR_LITERAL
- | STRING_LITERAL
- | NUM_FLOAT
- | NUM_LONG
- | NUM_DOUBLE
- ;
+ : NUM_INT
+ | CHAR_LITERAL
+ | STRING_LITERAL
+ | NUM_FLOAT
+ | NUM_LONG
+ | NUM_DOUBLE
+ ;
//----------------------------------------------------------------------------
// The Java scanner
@@ -1068,121 +1068,121 @@ constant
class JavaLexer extends Lexer;
options {
- exportVocab=Java; // call the vocabulary "Java"
- testLiterals=false; // don't automatically test for literals
- k=4; // four characters of lookahead
- charVocabulary='\u0003'..'\u7FFE';
- // without inlining some bitset tests, couldn't do unicode;
- // I need to make ANTLR generate smaller bitsets; see
- // bottom of JavaLexer.java
- codeGenBitsetTestThreshold=20;
+ exportVocab=Java; // call the vocabulary "Java"
+ testLiterals=false; // don't automatically test for literals
+ k=4; // four characters of lookahead
+ charVocabulary='\u0003'..'\u7FFE';
+ // without inlining some bitset tests, couldn't do unicode;
+ // I need to make ANTLR generate smaller bitsets; see
+ // bottom of JavaLexer.java
+ codeGenBitsetTestThreshold=20;
}
// OPERATORS
-QUESTION : '?' ;
-LPAREN : '(' ;
-RPAREN : ')' ;
-LBRACK : '[' ;
-RBRACK : ']' ;
-LCURLY : '{' ;
-RCURLY : '}' ;
-COLON : ':' ;
-COMMA : ',' ;
-//DOT : '.' ;
-ASSIGN : '=' ;
-EQUAL : "==" ;
-LNOT : '!' ;
-BNOT : '~' ;
-NOT_EQUAL : "!=" ;
-DIV : '/' ;
-DIV_ASSIGN : "/=" ;
-PLUS : '+' ;
-PLUS_ASSIGN : "+=" ;
-INC : "++" ;
-MINUS : '-' ;
-MINUS_ASSIGN : "-=" ;
-DEC : "--" ;
-STAR : '*' ;
-STAR_ASSIGN : "*=" ;
-MOD : '%' ;
-MOD_ASSIGN : "%=" ;
-SR : ">>" ;
-SR_ASSIGN : ">>=" ;
-BSR : ">>>" ;
-BSR_ASSIGN : ">>>=" ;
-GE : ">=" ;
-GT : ">" ;
-SL : "<<" ;
-SL_ASSIGN : "<<=" ;
-LE : "<=" ;
-LT : '<' ;
-BXOR : '^' ;
-BXOR_ASSIGN : "^=" ;
-BOR : '|' ;
-BOR_ASSIGN : "|=" ;
-LOR : "||" ;
-BAND : '&' ;
-BAND_ASSIGN : "&=" ;
-LAND : "&&" ;
-SEMI : ';' ;
+QUESTION : '?' ;
+LPAREN : '(' ;
+RPAREN : ')' ;
+LBRACK : '[' ;
+RBRACK : ']' ;
+LCURLY : '{' ;
+RCURLY : '}' ;
+COLON : ':' ;
+COMMA : ',' ;
+//DOT : '.' ;
+ASSIGN : '=' ;
+EQUAL : "==" ;
+LNOT : '!' ;
+BNOT : '~' ;
+NOT_EQUAL : "!=" ;
+DIV : '/' ;
+DIV_ASSIGN : "/=" ;
+PLUS : '+' ;
+PLUS_ASSIGN : "+=" ;
+INC : "++" ;
+MINUS : '-' ;
+MINUS_ASSIGN : "-=" ;
+DEC : "--" ;
+STAR : '*' ;
+STAR_ASSIGN : "*=" ;
+MOD : '%' ;
+MOD_ASSIGN : "%=" ;
+SR : ">>" ;
+SR_ASSIGN : ">>=" ;
+BSR : ">>>" ;
+BSR_ASSIGN : ">>>=" ;
+GE : ">=" ;
+GT : ">" ;
+SL : "<<" ;
+SL_ASSIGN : "<<=" ;
+LE : "<=" ;
+LT : '<' ;
+BXOR : '^' ;
+BXOR_ASSIGN : "^=" ;
+BOR : '|' ;
+BOR_ASSIGN : "|=" ;
+LOR : "||" ;
+BAND : '&' ;
+BAND_ASSIGN : "&=" ;
+LAND : "&&" ;
+SEMI : ';' ;
// Whitespace -- ignored
-WS : ( ' '
- | '\t'
- | '\f'
- // handle newlines
- | ( options {generateAmbigWarnings=false;}
- : "\r\n" // Evil DOS
- | '\r' // Macintosh
- | '\n' // Unix (the right way)
- )
- { newline(); }
- )+
- { _ttype = Token.SKIP; }
- ;
+WS : ( ' '
+ | '\t'
+ | '\f'
+ // handle newlines
+ | ( options {generateAmbigWarnings=false;}
+ : "\r\n" // Evil DOS
+ | '\r' // Macintosh
+ | '\n' // Unix (the right way)
+ )
+ { newline(); }
+ )+
+ { _ttype = Token.SKIP; }
+ ;
// Single-line comments
SL_COMMENT
- : "//"
- (~('\n'|'\r'))* ('\n'|'\r'('\n')?)?
- {$setType(Token.SKIP); newline();}
- ;
+ : "//"
+ (~('\n'|'\r'))* ('\n'|'\r'('\n')?)?
+ {$setType(Token.SKIP); newline();}
+ ;
// multiple-line comments
ML_COMMENT
- : "/*"
- ( /* '\r' '\n' can be matched in one alternative or by matching
- '\r' in one iteration and '\n' in another. I am trying to
- handle any flavor of newline that comes in, but the language
- that allows both "\r\n" and "\r" and "\n" to all be valid
- newline is ambiguous. Consequently, the resulting grammar
- must be ambiguous. I'm shutting this warning off.
- */
- options {
- generateAmbigWarnings=false;
- }
- :
- { LA(2)!='/' }? '*'
- | '\r' '\n' {newline();}
- | '\r' {newline();}
- | '\n' {newline();}
- | ~('*'|'\n'|'\r')
- )*
- "*/"
- {$setType(Token.SKIP);}
- ;
+ : "/*"
+ ( /* '\r' '\n' can be matched in one alternative or by matching
+ '\r' in one iteration and '\n' in another. I am trying to
+ handle any flavor of newline that comes in, but the language
+ that allows both "\r\n" and "\r" and "\n" to all be valid
+ newline is ambiguous. Consequently, the resulting grammar
+ must be ambiguous. I'm shutting this warning off.
+ */
+ options {
+ generateAmbigWarnings=false;
+ }
+ :
+ { LA(2)!='/' }? '*'
+ | '\r' '\n' {newline();}
+ | '\r' {newline();}
+ | '\n' {newline();}
+ | ~('*'|'\n'|'\r')
+ )*
+ "*/"
+ {$setType(Token.SKIP);}
+ ;
// character literals
CHAR_LITERAL
- : '\'' ( ESC | ~('\''|'\n'|'\r'|'\\') ) '\''
- ;
+ : '\'' ( ESC | ~('\''|'\n'|'\r'|'\\') ) '\''
+ ;
// string literals
STRING_LITERAL
- : '"' (ESC|~('"'|'\\'|'\n'|'\r'))* '"'
- ;
+ : '"' (ESC|~('"'|'\\'|'\n'|'\r'))* '"'
+ ;
// escape sequence -- note that this is protected; it can only be called
@@ -1195,121 +1195,132 @@ STRING_LITERAL
// the FOLLOW ambig warnings.
protected
ESC
- : '\\'
- ( 'n'
- | 'r'
- | 't'
- | 'b'
- | 'f'
- | '"'
- | '\''
- | '\\'
- | ('u')+ HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
- | '0'..'3'
- (
- options {
- warnWhenFollowAmbig = false;
- }
- : '0'..'7'
- (
- options {
- warnWhenFollowAmbig = false;
- }
- : '0'..'7'
- )?
- )?
- | '4'..'7'
- (
- options {
- warnWhenFollowAmbig = false;
- }
- : '0'..'7'
- )?
- )
- ;
+ : '\\'
+ ( 'n'
+ | 'r'
+ | 't'
+ | 'b'
+ | 'f'
+ | '"'
+ | '\''
+ | '\\'
+ | ('u')+ HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
+ | '0'..'3'
+ (
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ : '0'..'7'
+ (
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ : '0'..'7'
+ )?
+ )?
+ | '4'..'7'
+ (
+ options {
+ warnWhenFollowAmbig = false;
+ }
+ : '0'..'7'
+ )?
+ )
+ ;
// hexadecimal digit (again, note it's protected!)
protected
HEX_DIGIT
- : ('0'..'9'|'A'..'F'|'a'..'f')
- ;
+ : ('0'..'9'|'A'..'F'|'a'..'f')
+ ;
// an identifier. Note that testLiterals is set to true! This means
// that after we match the rule, we look in the literals table to see
// if it's a literal or really an identifer
IDENT
- options {testLiterals=true;}
- : ('a'..'z'|'A'..'Z'|'_'|'$') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'$')*
- ;
+ options {testLiterals=true;}
+ : ('a'..'z'|'A'..'Z'|'_'|'$') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'$')*
+ ;
// a numeric literal
NUM_INT
- {boolean isDecimal=false; Token t=null;}
+ {boolean isDecimal=false, isHexadecimal=false; Token t=null;}
: '.' {_ttype = DOT;}
- ( ('0'..'9')+ (EXPONENT)? (f1:FLOAT_SUFFIX {t=f1;})?
+ ( ('0'..'9')+ (EXPONENT)? (f1:FLOAT_SUFFIX {t=f1;})?
{
- if (t != null && t.getText().toUpperCase().indexOf('F')>=0) {
- _ttype = NUM_FLOAT;
- }
- else {
- _ttype = NUM_DOUBLE; // assume double
- }
- }
+ if (t != null && t.getText().toUpperCase().indexOf('F')>=0) {
+ _ttype = NUM_FLOAT;
+ }
+ else {
+ _ttype = NUM_DOUBLE; // assume double
+ }
+ }
)?
- | ( '0' {isDecimal = true;} // special case for just '0'
- ( ('x'|'X')
- ( // hex
- // the 'e'|'E' and float suffix stuff look
- // like hex digits, hence the (...)+ doesn't
- // know when to stop: ambig. ANTLR resolves
- // it correctly by matching immediately. It
- // is therefor ok to hush warning.
- options {
- warnWhenFollowAmbig=false;
- }
- : HEX_DIGIT
- )+
-
- | //float or double with leading zero
- (('0'..'9')+ ('.'|EXPONENT|FLOAT_SUFFIX)) => ('0'..'9')+
-
- | ('0'..'7')+ // octal
- )?
- | ('1'..'9') ('0'..'9')* {isDecimal=true;} // non-zero decimal
- )
- ( ('l'|'L') { _ttype = NUM_LONG; }
-
- // only check to see if it's a float if looks like decimal so far
- | {isDecimal}?
- ( '.' ('0'..'9')* (EXPONENT)? (f2:FLOAT_SUFFIX {t=f2;})?
- | EXPONENT (f3:FLOAT_SUFFIX {t=f3;})?
- | f4:FLOAT_SUFFIX {t=f4;}
- )
- {
- if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0) {
- _ttype = NUM_FLOAT;
- }
- else {
- _ttype = NUM_DOUBLE; // assume double
- }
- }
+ | ( '0' {isDecimal = true;} // special case for just '0'
+ ( ('x'|'X') { isHexadecimal=true; } // hex
+ (
+ // the 'e'|'E' and float suffix stuff look
+ // like hex digits, hence the (...)+ doesn't
+ // know when to stop: ambig. ANTLR resolves
+ // it correctly by matching immediately. It
+ // is therefor ok to hush warning.
+ options {
+ warnWhenFollowAmbig=false;
+ }
+ : HEX_DIGIT
+ )+
+
+ | //float or double with leading zero
+ (('0'..'9')+ ('.'|EXPONENT|FLOAT_SUFFIX)) => ('0'..'9')+
+
+ | ('0'..'7')+ // octal
+ )?
+ | ('1'..'9') ('0'..'9')* {isDecimal=true;} // non-zero decimal
+ )
+ (
+ ('l'|'L') { _ttype = NUM_LONG; }
+
+ // check to see if it's a hexadecimal w/ binary exponent float if looks like hexadecimal so far
+ | {isHexadecimal}?
+ ( '.' ( options { warnWhenFollowAmbig=false; } : HEX_DIGIT )* )?
+ ('p'|'P') ('+'|'-')? ('0'..'9')+ (f5:FLOAT_SUFFIX {t=f5;})?
+ {
+ if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0) {
+ _ttype = NUM_FLOAT;
+ } else {
+ _ttype = NUM_DOUBLE; // assume double
+ }
+ }
+ // check to see if it's a float if looks like decimal so far
+ | {isDecimal}?
+ ( '.' ('0'..'9')* (EXPONENT)? (f2:FLOAT_SUFFIX {t=f2;})?
+ | EXPONENT (f3:FLOAT_SUFFIX {t=f3;})?
+ | f4:FLOAT_SUFFIX {t=f4;}
+ )
+ {
+ if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0) {
+ _ttype = NUM_FLOAT;
+ } else {
+ _ttype = NUM_DOUBLE; // assume double
+ }
+ }
)?
- ;
+ ;
// a couple protected methods to assist in matching floating point numbers
protected
EXPONENT
- : ('e'|'E') ('+'|'-')? ('0'..'9')+
- ;
+ : ('e'|'E') (PLUS|MINUS)? ('0'..'9')+
+ ;
protected
FLOAT_SUFFIX
- : 'f'|'F'|'d'|'D'
- ;
+ : 'f'|'F'|'d'|'D'
+ ;