1040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato/*
2040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato * Copyright (C) 2011 Google Inc.
3040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato *
4040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato * Licensed under the Apache License, Version 2.0 (the "License");
5040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato * you may not use this file except in compliance with the License.
6040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato * You may obtain a copy of the License at
7040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato *
8040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato * http://www.apache.org/licenses/LICENSE-2.0
9040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato *
10040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato * Unless required by applicable law or agreed to in writing, software
11040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato * distributed under the License is distributed on an "AS IS" BASIS,
12040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato * See the License for the specific language governing permissions and
14040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato * limitations under the License.
15040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato */
16040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
17040992567205c3b6e4ee01bfb2893bceb915357cJoe Onoratopackage com.google.doclava.apicheck;
18040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
19040992567205c3b6e4ee01bfb2893bceb915357cJoe Onoratoimport com.google.doclava.AnnotationInstanceInfo;
20040992567205c3b6e4ee01bfb2893bceb915357cJoe Onoratoimport com.google.doclava.ClassInfo;
21040992567205c3b6e4ee01bfb2893bceb915357cJoe Onoratoimport com.google.doclava.Converter;
22040992567205c3b6e4ee01bfb2893bceb915357cJoe Onoratoimport com.google.doclava.FieldInfo;
23040992567205c3b6e4ee01bfb2893bceb915357cJoe Onoratoimport com.google.doclava.MethodInfo;
24040992567205c3b6e4ee01bfb2893bceb915357cJoe Onoratoimport com.google.doclava.PackageInfo;
25040992567205c3b6e4ee01bfb2893bceb915357cJoe Onoratoimport com.google.doclava.ParameterInfo;
26040992567205c3b6e4ee01bfb2893bceb915357cJoe Onoratoimport com.google.doclava.SourcePositionInfo;
27040992567205c3b6e4ee01bfb2893bceb915357cJoe Onoratoimport com.google.doclava.TypeInfo;
28040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
29d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport java.io.IOException;
30d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport java.io.InputStream;
31d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport java.util.ArrayList;
32d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport java.util.LinkedList;
33d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
34040992567205c3b6e4ee01bfb2893bceb915357cJoe Onoratoclass ApiFile {
35040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
36040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  public static ApiInfo parseApi(String filename, InputStream stream) throws ApiParseException {
37040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    final int CHUNK = 1024*1024;
38040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    int hint = 0;
39040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    try {
40040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      hint = stream.available() + CHUNK;
41040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } catch (IOException ex) {
42040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
43040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (hint < CHUNK) {
44040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      hint = CHUNK;
45040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
46040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    byte[] buf = new byte[hint];
47040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    int size = 0;
48040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
49040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    try {
50040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      while (true) {
51040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        if (size == buf.length) {
52040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          byte[] tmp = new byte[buf.length+CHUNK];
53040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          System.arraycopy(buf, 0, tmp, 0, buf.length);
54040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          buf = tmp;
55040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
56040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        int amt = stream.read(buf, size, (buf.length-size));
57040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        if (amt < 0) {
58040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          break;
59040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        } else {
60040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          size += amt;
61040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
62040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
63040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } catch (IOException ex) {
64040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throw new ApiParseException("Error reading API file", ex);
65040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
66040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
67040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    final Tokenizer tokenizer = new Tokenizer(filename, (new String(buf, 0, size)).toCharArray());
68040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    final ApiInfo api = new ApiInfo();
69040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
70040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    while (true) {
71040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      String token = tokenizer.getToken();
72040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (token == null) {
73040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        break;
74040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
75040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if ("package".equals(token)) {
76040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        parsePackage(api, tokenizer);
77040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else {
78040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        throw new ApiParseException("expected package got " + token, tokenizer.getLine());
79040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
80040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
81040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
82040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    api.resolveSuperclasses();
83040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    api.resolveInterfaces();
84040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
85040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    return api;
86040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
87040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
88040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  private static void parsePackage(ApiInfo api, Tokenizer tokenizer)
89040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throws ApiParseException {
90040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    String token;
91040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    String name;
92040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    PackageInfo pkg;
93040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
94040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    token = tokenizer.requireToken();
95040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    assertIdent(tokenizer, token);
96040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    name = token;
97040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    pkg = new PackageInfo(name, tokenizer.pos());
98040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    token = tokenizer.requireToken();
99040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (!"{".equals(token)) {
100040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throw new ApiParseException("expected '{' got " + token, tokenizer.getLine());
101040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
102040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    while (true) {
103040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
104040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if ("}".equals(token)) {
105040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        break;
106040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else {
107040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        parseClass(api, pkg, tokenizer, token);
108040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
109040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
110040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    api.addPackage(pkg);
111040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
112040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
113040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  private static void parseClass(ApiInfo api, PackageInfo pkg, Tokenizer tokenizer, String token)
114040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throws ApiParseException {
115040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean pub = false;
116040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean prot = false;
117040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean pkgpriv = false;
118040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean stat = false;
119040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean fin = false;
120040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean abs = false;
121040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean dep = false;
122040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean iface;
123040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    String name;
124040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    String qname;
125040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    String ext = null;
126040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    ClassInfo cl;
127040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
128040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("public".equals(token)) {
129040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      pub = true;
130040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
131040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } else if ("protected".equals(token)) {
132040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      prot = true;
133040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
134040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } else {
135040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      pkgpriv = true;
136040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
137040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("static".equals(token)) {
138040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      stat = true;
139040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
140040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
141040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("final".equals(token)) {
142040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      fin = true;
143040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
144040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
145040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("abstract".equals(token)) {
146040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      abs = true;
147040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
148040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
149040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("deprecated".equals(token)) {
150040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      dep = true;
151040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
152040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
153040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("class".equals(token)) {
154040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      iface = false;
155040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
156040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } else if ("interface".equals(token)) {
157040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      iface = true;
158040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
159040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } else {
160040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throw new ApiParseException("missing class or interface. got: " + token, tokenizer.getLine());
161040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
162040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    assertIdent(tokenizer, token);
163040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    name = token;
164040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    token = tokenizer.requireToken();
165040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    qname = qualifiedName(pkg.name(), name, null);
166040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    cl = new ClassInfo(null/*classDoc*/, ""/*rawCommentText*/, tokenizer.pos(), pub, prot,
167040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        pkgpriv, false/*isPrivate*/, stat, iface, abs, true/*isOrdinaryClass*/,
168040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        false/*isException*/, false/*isError*/, false/*isEnum*/, false/*isAnnotation*/,
169040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        fin, false/*isIncluded*/, name, qname, null/*qualifiedTypeName*/, false/*isPrimitive*/);
170040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    cl.setDeprecated(dep);
171040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("extends".equals(token)) {
172040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
173040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      assertIdent(tokenizer, token);
174040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      ext = token;
175040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
176040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
177040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    // Resolve superclass after done parsing
178040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    api.mapClassToSuper(cl, ext);
179040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    final TypeInfo typeInfo = Converter.obtainTypeFromString(qname) ;
180040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    cl.setTypeInfo(typeInfo);
181d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    cl.setAnnotations(new ArrayList<AnnotationInstanceInfo>());
182040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("implements".equals(token)) {
183040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      while (true) {
184040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        token = tokenizer.requireToken();
185040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        if ("{".equals(token)) {
186040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          break;
187040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        } else {
188040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          /// TODO
189040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          if (!",".equals(token)) {
190040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            api.mapClassToInterface(cl, token);
191040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          }
192040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
193040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
194040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
195040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (!"{".equals(token)) {
196040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throw new ApiParseException("expected {", tokenizer.getLine());
197040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
198040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    token = tokenizer.requireToken();
199040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    while (true) {
200040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if ("}".equals(token)) {
201040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        break;
202040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if ("ctor".equals(token)) {
203040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        token = tokenizer.requireToken();
204040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        parseConstructor(tokenizer, cl, token);
205040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if ("method".equals(token)) {
206040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        token = tokenizer.requireToken();
207040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        parseMethod(tokenizer, cl, token);
208040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if ("field".equals(token)) {
209040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        token = tokenizer.requireToken();
210132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato        parseField(tokenizer, cl, token, false);
211132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato      } else if ("enum_constant".equals(token)) {
212132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato        token = tokenizer.requireToken();
213132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato        parseField(tokenizer, cl, token, true);
214040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else {
215132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato        throw new ApiParseException("expected ctor, enum_constant, field or method", tokenizer.getLine());
216040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
217040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
218040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
219040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    pkg.addClass(cl);
220040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
221040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
222040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  private static void parseConstructor(Tokenizer tokenizer, ClassInfo cl, String token)
223040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throws ApiParseException {
224040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean pub = false;
225040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean prot = false;
226040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean pkgpriv = false;
227040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean dep = false;
228040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    String name;
229040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    MethodInfo method;
230040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
231040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("public".equals(token)) {
232040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      pub = true;
233040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
234040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } else if ("protected".equals(token)) {
235040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      prot = true;
236040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
237040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } else {
238040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      pkgpriv = true;
239040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
240040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("deprecated".equals(token)) {
241040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      dep = true;
242040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
243040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
244040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    assertIdent(tokenizer, token);
245040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    name = token;
246040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    token = tokenizer.requireToken();
247040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (!"(".equals(token)) {
248040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throw new ApiParseException("expected (", tokenizer.getLine());
249040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
250040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    //method = new MethodInfo(name, cl.qualifiedName(), false/*static*/, false/*final*/, dep,
251040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    //    pub ? "public" : "protected", tokenizer.pos(), cl);
252d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    method = new MethodInfo(""/*rawCommentText*/, new ArrayList<TypeInfo>()/*typeParameters*/,
253040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        name, null/*signature*/, cl, cl, pub, prot, pkgpriv, false/*isPrivate*/, false/*isFinal*/,
254040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        false/*isStatic*/, false/*isSynthetic*/, false/*isAbstract*/, false/*isSynthetic*/,
255040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        false/*isNative*/,
256040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        false /*isAnnotationElement*/, "constructor", null/*flatSignature*/,
257d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        null/*overriddenMethod*/, cl.asTypeInfo(), new ArrayList<ParameterInfo>(),
258d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        new ArrayList<ClassInfo>()/*thrownExceptions*/, tokenizer.pos(),
259d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        new ArrayList<AnnotationInstanceInfo>()/*annotations*/);
260040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    method.setDeprecated(dep);
261040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    token = tokenizer.requireToken();
262040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    parseParameterList(tokenizer, method, token);
263040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    token = tokenizer.requireToken();
264040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("throws".equals(token)) {
265040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = parseThrows(tokenizer, method);
266040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
267040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (!";".equals(token)) {
268040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throw new ApiParseException("expected ; found " + token, tokenizer.getLine());
269040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
270040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    cl.addConstructor(method);
271040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
272040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
273040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  private static void parseMethod(Tokenizer tokenizer, ClassInfo cl, String token)
274040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throws ApiParseException {
275040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean pub = false;
276040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean prot = false;
277040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean pkgpriv = false;
278040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean stat = false;
279040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean fin = false;
280040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean abs = false;
281040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean dep = false;
282040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean syn = false;
283040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    String type;
284040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    String name;
285040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    String ext = null;
286040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    MethodInfo method;
287040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
288040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("public".equals(token)) {
289040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      pub = true;
290040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
291040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } else if ("protected".equals(token)) {
292040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      prot = true;
293040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
294040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } else {
295040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      pkgpriv = true;
296040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
297040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("static".equals(token)) {
298040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      stat = true;
299040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
300040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
301040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("final".equals(token)) {
302040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      fin = true;
303040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
304040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
305040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("abstract".equals(token)) {
306040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      abs = true;
307040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
308040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
309040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("deprecated".equals(token)) {
310040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      dep = true;
311040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
312040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
313040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("synchronized".equals(token)) {
314040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      syn = true;
315040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
316040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
317040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    assertIdent(tokenizer, token);
318040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    type = token;
319040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    token = tokenizer.requireToken();
320040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    assertIdent(tokenizer, token);
321040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    name = token;
322d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    method = new MethodInfo(""/*rawCommentText*/, new ArrayList<TypeInfo>()/*typeParameters*/,
323040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        name, null/*signature*/, cl, cl, pub, prot, pkgpriv, false/*isPrivate*/, fin,
324040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        stat, false/*isSynthetic*/, abs/*isAbstract*/, syn, false/*isNative*/,
325040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        false /*isAnnotationElement*/, "method", null/*flatSignature*/, null/*overriddenMethod*/,
326d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Converter.obtainTypeFromString(type), new ArrayList<ParameterInfo>(),
327d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        new ArrayList<ClassInfo>()/*thrownExceptions*/, tokenizer.pos(),
328d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        new ArrayList<AnnotationInstanceInfo>()/*annotations*/);
329040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    method.setDeprecated(dep);
330040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    token = tokenizer.requireToken();
331040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (!"(".equals(token)) {
332040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throw new ApiParseException("expected (", tokenizer.getLine());
333040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
334040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    token = tokenizer.requireToken();
335040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    parseParameterList(tokenizer, method, token);
336040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    token = tokenizer.requireToken();
337040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("throws".equals(token)) {
338040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = parseThrows(tokenizer, method);
339040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
340040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (!";".equals(token)) {
341040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throw new ApiParseException("expected ; found " + token, tokenizer.getLine());
342040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
343040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    cl.addMethod(method);
344040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
345040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
346132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato  private static void parseField(Tokenizer tokenizer, ClassInfo cl, String token, boolean isEnum)
347040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throws ApiParseException {
348040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean pub = false;
349040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean prot = false;
350040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean pkgpriv = false;
351040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean stat = false;
352040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean fin = false;
353040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean dep = false;
354040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean trans = false;
355040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean vol = false;
356040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    String type;
357040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    String name;
358040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    String val = null;
359040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Object v;
360040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    FieldInfo field;
361040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
362040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("public".equals(token)) {
363040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      pub = true;
364040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
365040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } else if ("protected".equals(token)) {
366040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      prot = true;
367040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
368040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } else {
369040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      pkgpriv = true;
370040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
371040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("static".equals(token)) {
372040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      stat = true;
373040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
374040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
375040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("final".equals(token)) {
376040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      fin = true;
377040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
378040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
379040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("deprecated".equals(token)) {
380040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      dep = true;
381040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
382040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
383040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("transient".equals(token)) {
384040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      trans = true;
385040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
386040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
387040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("volatile".equals(token)) {
388040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      vol = true;
389040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
390040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
391040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    assertIdent(tokenizer, token);
392040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    type = token;
393040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    token = tokenizer.requireToken();
394040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    assertIdent(tokenizer, token);
395040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    name = token;
396040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    token = tokenizer.requireToken();
397040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("=".equals(token)) {
398040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken(false);
399040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      val = token;
400040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
401040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
402040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (!";".equals(token)) {
403040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throw new ApiParseException("expected ; found " + token, tokenizer.getLine());
404040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
405040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    try {
406040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      v = parseValue(type, val);
407040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } catch (ApiParseException ex) {
408040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      ex.line = tokenizer.getLine();
409040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throw ex;
410040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
411040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    field = new FieldInfo(name, cl, cl, pub, prot, pkgpriv, false/*isPrivate*/, fin, stat,
412040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        trans, vol, false, Converter.obtainTypeFromString(type), "", v, tokenizer.pos(),
413d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        new ArrayList<AnnotationInstanceInfo>());
414040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    field.setDeprecated(dep);
415132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato    if (isEnum) {
416132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato      cl.addEnumConstant(field);
417132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato    } else {
418132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato      cl.addField(field);
419132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato    }
420040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
421040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
422040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  public static Object parseValue(String type, String val) throws ApiParseException {
423040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (val != null) {
424040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if ("boolean".equals(type)) {
425040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        return "true".equals(val) ? Boolean.TRUE : Boolean.FALSE;
426040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if ("byte".equals(type)) {
427040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        return Integer.valueOf(val);
428040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if ("short".equals(type)) {
429040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        return Integer.valueOf(val);
430040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if ("int".equals(type)) {
431040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        return Integer.valueOf(val);
432040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if ("long".equals(type)) {
433040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        return Long.valueOf(val.substring(0, val.length()-1));
434040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if ("float".equals(type)) {
4351e0d370c6a4c165cb8c74f53cb035e5521e0cd87Jeff Hamilton        if ("(1.0f/0.0f)".equals(val) || "(1.0f / 0.0f)".equals(val)) {
436040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          return Float.POSITIVE_INFINITY;
4371e0d370c6a4c165cb8c74f53cb035e5521e0cd87Jeff Hamilton        } else if ("(-1.0f/0.0f)".equals(val) || "(-1.0f / 0.0f)".equals(val)) {
438040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          return Float.NEGATIVE_INFINITY;
4391e0d370c6a4c165cb8c74f53cb035e5521e0cd87Jeff Hamilton        } else if ("(0.0f/0.0f)".equals(val) || "(0.0f / 0.0f)".equals(val)) {
440040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          return Float.NaN;
441040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        } else {
442040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          return Float.valueOf(val);
443040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
444040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if ("double".equals(type)) {
4451e0d370c6a4c165cb8c74f53cb035e5521e0cd87Jeff Hamilton        if ("(1.0/0.0)".equals(val) || "(1.0 / 0.0)".equals(val)) {
446040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          return Double.POSITIVE_INFINITY;
4471e0d370c6a4c165cb8c74f53cb035e5521e0cd87Jeff Hamilton        } else if ("(-1.0/0.0)".equals(val) || "(-1.0 / 0.0)".equals(val)) {
448040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          return Double.NEGATIVE_INFINITY;
4491e0d370c6a4c165cb8c74f53cb035e5521e0cd87Jeff Hamilton        } else if ("(0.0/0.0)".equals(val) || "(0.0 / 0.0)".equals(val)) {
450040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          return Double.NaN;
451040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        } else {
452040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          return Double.valueOf(val);
453040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
454040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if ("char".equals(type)) {
455040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        return new Integer((char)Integer.parseInt(val));
456040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if ("java.lang.String".equals(type)) {
457040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        if ("null".equals(val)) {
458040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          return null;
459040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        } else {
460040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          return FieldInfo.javaUnescapeString(val.substring(1, val.length()-1));
461040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
462040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
463040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
464040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if ("null".equals(val)) {
465040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return null;
466040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } else {
467040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return val;
468040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
469040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
470040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
471040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  private static void parseParameterList(Tokenizer tokenizer, AbstractMethodInfo method,
472040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      String token) throws ApiParseException {
473040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    while (true) {
474040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (")".equals(token)) {
475040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        return;
476040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
477040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
478040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      String type = token;
479040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      String name = null;
480040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
481040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (isIdent(token)) {
482040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        name = token;
483040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        token = tokenizer.requireToken();
484040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
485040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (",".equals(token)) {
486040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        token = tokenizer.requireToken();
487040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if (")".equals(token)) {
488040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else {
489040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        throw new ApiParseException("expected , found " + token, tokenizer.getLine());
490040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
491040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      method.addParameter(new ParameterInfo(name, type,
492040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            Converter.obtainTypeFromString(type),
493040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            type.endsWith("..."),
494040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            tokenizer.pos()));
495040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (type.endsWith("...")) {
496040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        method.setVarargs(true);
497040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
498040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
499040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
500040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
501040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  private static String parseThrows(Tokenizer tokenizer, AbstractMethodInfo method)
502040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throws ApiParseException {
503040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    String token = tokenizer.requireToken();
504040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean comma = true;
505040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    while (true) {
506040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (";".equals(token)) {
507040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        return token;
508040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if (",".equals(token)) {
509040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        if (comma) {
510040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          throw new ApiParseException("Expected exception, got ','", tokenizer.getLine());
511040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
512040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        comma = true;
513040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else {
514040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        if (!comma) {
515040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          throw new ApiParseException("Expected ',' or ';' got " + token, tokenizer.getLine());
516040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
517040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        comma = false;
518040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        method.addException(token);
519040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
520040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      token = tokenizer.requireToken();
521040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
522040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
523040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
524040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  private static String qualifiedName(String pkg, String className, ClassInfo parent) {
525040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    String parentQName = (parent != null) ? (parent.qualifiedName() + ".") : "";
526040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    return pkg + "." + parentQName + className;
527040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
528040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
529040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  public static boolean isIdent(String token) {
530040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    return isident(token.charAt(0));
531040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
532040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
533040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  public static void assertIdent(Tokenizer tokenizer, String token) throws ApiParseException {
534040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (!isident(token.charAt(0))) {
535040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      throw new ApiParseException("Expected identifier: " + token, tokenizer.getLine());
536040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
537040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
538040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
539040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static class Tokenizer {
540040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    char[] mBuf;
541040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    String mFilename;
542040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    int mPos;
543040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    int mLine = 1;
544040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Tokenizer(String filename, char[] buf) {
545040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      mFilename = filename;
546040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      mBuf = buf;
547040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
548040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
549040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    public SourcePositionInfo pos() {
550040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return new SourcePositionInfo(mFilename, mLine, 0);
551040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
552040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
553040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    public int getLine() {
554040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return mLine;
555040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
556040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
557040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean eatWhitespace() {
558040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      boolean ate = false;
559040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      while (mPos < mBuf.length && isspace(mBuf[mPos])) {
560040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        if (mBuf[mPos] == '\n') {
561040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          mLine++;
562040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
563040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        mPos++;
564040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        ate = true;
565040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
566040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return ate;
567040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
568040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
569040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean eatComment() {
570040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (mPos+1 < mBuf.length) {
571040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        if (mBuf[mPos] == '/' && mBuf[mPos+1] == '/') {
572040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          mPos += 2;
573040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          while (mPos < mBuf.length && !isnewline(mBuf[mPos])) {
574040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            mPos++;
575040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          }
576040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          return true;
577040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
578040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
579040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return false;
580040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
581040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
582040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    void eatWhitespaceAndComments() {
583040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      while (eatWhitespace() || eatComment()) {
584040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
585040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
586040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
587040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    public String requireToken() throws ApiParseException {
588040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return requireToken(true);
589040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
590040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
591040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    public String requireToken(boolean parenIsSep) throws ApiParseException {
592040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      final String token = getToken(parenIsSep);
593040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (token != null) {
594040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        return token;
595040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else {
596040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        throw new ApiParseException("Unexpected end of file", mLine);
597040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
598040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
599040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
600040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    public String getToken() throws ApiParseException {
601040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return getToken(true);
602040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
603040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
604040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    public String getToken(boolean parenIsSep) throws ApiParseException {
605040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      eatWhitespaceAndComments();
606040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (mPos >= mBuf.length) {
607040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        return null;
608040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
609040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      final int line = mLine;
610040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      final char c = mBuf[mPos];
611040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      final int start = mPos;
612040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      mPos++;
613040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (c == '"') {
614040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        final int STATE_BEGIN = 0;
615040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        final int STATE_ESCAPE = 1;
616040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        int state = STATE_BEGIN;
617040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        while (true) {
618040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          if (mPos >= mBuf.length) {
619040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            throw new ApiParseException("Unexpected end of file for \" starting at " + line, mLine);
620040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          }
621040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          final char k = mBuf[mPos];
622040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          if (k == '\n' || k == '\r') {
623040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            throw new ApiParseException("Unexpected newline for \" starting at " + line, mLine);
624040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          }
625040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          mPos++;
626040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          switch (state) {
627040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            case STATE_BEGIN:
628040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato              switch (k) {
629040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato                case '\\':
630040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato                  state = STATE_ESCAPE;
631040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato                  mPos++;
632040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato                  break;
633040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato                case '"':
634040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato                  return new String(mBuf, start, mPos-start);
635040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato              }
636040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            case STATE_ESCAPE:
637040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato              state = STATE_BEGIN;
638040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato              break;
639040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          }
640040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
641040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if (issep(c, parenIsSep)) {
642040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        return "" + c;
643040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else {
644040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        int genericDepth = 0;
645040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        do {
646040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          while (mPos < mBuf.length && !isspace(mBuf[mPos]) && !issep(mBuf[mPos], parenIsSep)) {
647040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            mPos++;
648040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          }
649040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          if (mPos < mBuf.length) {
650040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            if (mBuf[mPos] == '<') {
651040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato              genericDepth++;
652040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato              mPos++;
653040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            } else if (mBuf[mPos] == '>') {
654040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato              genericDepth--;
655040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato              mPos++;
656040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            } else if (genericDepth != 0) {
657040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato              mPos++;
658040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            }
659040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          }
660040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        } while (mPos < mBuf.length
661040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            && ((!isspace(mBuf[mPos]) && !issep(mBuf[mPos], parenIsSep)) || genericDepth != 0));
662040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        if (mPos >= mBuf.length) {
663040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          throw new ApiParseException("Unexpected end of file for \" starting at " + line, mLine);
664040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
665040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        return new String(mBuf, start, mPos-start);
666040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
667040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
668040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
669040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
670040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static boolean isspace(char c) {
671040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    return c == ' ' || c == '\t' || c == '\n' || c == '\r';
672040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
673040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
674040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static boolean isnewline(char c) {
675040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    return c == '\n' || c == '\r';
676040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
677040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
678040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static boolean issep(char c, boolean parenIsSep) {
679040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (parenIsSep) {
680040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (c == '(' || c == ')') {
681040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        return true;
682040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
683040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
684040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    return c == '{' || c == '}' || c == ',' || c == ';' || c == '<' || c == '>';
685040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
686040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
687040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static boolean isident(char c) {
688040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (c == '"' || issep(c, true)) {
689040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return false;
690040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
691040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    return true;
692040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
693040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato}
694040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
695