diff options
Diffstat (limited to 'java/com/google/turbine/parse')
-rw-r--r-- | java/com/google/turbine/parse/ConstExpressionParser.java | 53 | ||||
-rw-r--r-- | java/com/google/turbine/parse/IteratorLexer.java | 13 | ||||
-rw-r--r-- | java/com/google/turbine/parse/Lexer.java | 5 | ||||
-rw-r--r-- | java/com/google/turbine/parse/ParseError.java | 33 | ||||
-rw-r--r-- | java/com/google/turbine/parse/Parser.java | 107 | ||||
-rw-r--r-- | java/com/google/turbine/parse/StreamLexer.java | 48 | ||||
-rw-r--r-- | java/com/google/turbine/parse/UnicodeEscapePreprocessor.java | 17 |
7 files changed, 152 insertions, 124 deletions
diff --git a/java/com/google/turbine/parse/ConstExpressionParser.java b/java/com/google/turbine/parse/ConstExpressionParser.java index c3e4e88..7749b71 100644 --- a/java/com/google/turbine/parse/ConstExpressionParser.java +++ b/java/com/google/turbine/parse/ConstExpressionParser.java @@ -21,13 +21,13 @@ import static com.google.common.collect.Iterables.getOnlyElement; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.primitives.Ints; +import com.google.turbine.diag.TurbineError; import com.google.turbine.model.Const; import com.google.turbine.model.TurbineConstantTypeKind; import com.google.turbine.tree.Tree; import com.google.turbine.tree.Tree.ClassLiteral; import com.google.turbine.tree.Tree.ClassTy; import com.google.turbine.tree.Tree.Expression; -import com.google.turbine.tree.Tree.VoidTy; import com.google.turbine.tree.TurbineOperatorKind; import javax.annotation.Nullable; @@ -35,11 +35,12 @@ import javax.annotation.Nullable; public class ConstExpressionParser { Token token; + private int position; private final Lexer lexer; public ConstExpressionParser(Lexer lexer) { this.lexer = lexer; - token = lexer.next(); + eat(); } private static TurbineOperatorKind operator(Token token) { @@ -104,10 +105,12 @@ public class ConstExpressionParser { return finishLiteral(TurbineConstantTypeKind.FLOAT, negate); case TRUE: eat(); - return new Tree.Literal(TurbineConstantTypeKind.BOOLEAN, new Const.BooleanValue(true)); + return new Tree.Literal( + position, TurbineConstantTypeKind.BOOLEAN, new Const.BooleanValue(true)); case FALSE: eat(); - return new Tree.Literal(TurbineConstantTypeKind.BOOLEAN, new Const.BooleanValue(false)); + return new Tree.Literal( + position, TurbineConstantTypeKind.BOOLEAN, new Const.BooleanValue(false)); case CHAR_LITERAL: return finishLiteral(TurbineConstantTypeKind.CHAR, negate); case STRING_LITERAL: @@ -148,7 +151,7 @@ public class ConstExpressionParser { case BOOLEAN: return primitiveClassLiteral(TurbineConstantTypeKind.BOOLEAN); case VOID: - return primitiveClassLiteral(VoidTy.INSTANCE); + return primitiveClassLiteral(new Tree.VoidTy(position)); case AT: return annotation(); default: @@ -157,7 +160,7 @@ public class ConstExpressionParser { } private Expression primitiveClassLiteral(TurbineConstantTypeKind type) { - return primitiveClassLiteral(new Tree.PrimTy(type)); + return primitiveClassLiteral(new Tree.PrimTy(position, type)); } private Expression primitiveClassLiteral(Tree.Type type) { @@ -170,7 +173,7 @@ public class ConstExpressionParser { return null; } eat(); - return new ClassLiteral(type); + return new ClassLiteral(position, type); } private Tree.Expression maybeCast() { @@ -226,9 +229,7 @@ public class ConstExpressionParser { case NOT: case TILDE: case IDENT: - { - return new Tree.TypeCast(asClassTy(cvar.name()), primary(false)); - } + return new Tree.TypeCast(position, asClassTy(cvar.name()), primary(false)); default: return expr; } @@ -240,19 +241,20 @@ public class ConstExpressionParser { private ClassTy asClassTy(ImmutableList<String> names) { ClassTy cty = null; for (String bit : names) { - cty = new ClassTy(Optional.fromNullable(cty), bit, ImmutableList.<Tree.Type>of()); + cty = new ClassTy(position, Optional.fromNullable(cty), bit, ImmutableList.<Tree.Type>of()); } return cty; } private void eat() { token = lexer.next(); + position = lexer.position(); } private Tree.Expression arrayInitializer() { if (token == Token.RBRACE) { eat(); - return new Tree.ArrayInit(ImmutableList.<Tree.Expression>of()); + return new Tree.ArrayInit(position, ImmutableList.<Tree.Expression>of()); } ImmutableList.Builder<Tree.Expression> exprs = ImmutableList.builder(); @@ -278,7 +280,7 @@ public class ConstExpressionParser { return null; } } - return new Tree.ArrayInit(exprs.build()); + return new Tree.ArrayInit(position, exprs.build()); } /** Finish hex, decimal, octal, and binary integer literals (see JLS 3.10.1). */ @@ -345,10 +347,10 @@ public class ConstExpressionParser { value = new Const.StringValue(text); break; default: - throw error(kind); + throw error("%s", kind); } eat(); - return new Tree.Literal(kind, value); + return new Tree.Literal(position, kind, value); } /** @@ -399,11 +401,12 @@ public class ConstExpressionParser { if (expr == null) { return null; } - return new Tree.Unary(expr, op); + return new Tree.Unary(position, expr, op); } @Nullable private Tree.Expression qualIdent() { + int pos = position; ImmutableList.Builder<String> bits = ImmutableList.builder(); bits.add(lexer.stringValue()); eat(); @@ -416,13 +419,13 @@ public class ConstExpressionParser { case CLASS: // TODO(cushon): only allow in annotations? eat(); - return new Tree.ClassLiteral(asClassTy(bits.build())); + return new Tree.ClassLiteral(pos, asClassTy(bits.build())); default: return null; } eat(); } - return new Tree.ConstVarName(bits.build()); + return new Tree.ConstVarName(pos, bits.build()); } public Tree.Expression expression() { @@ -465,7 +468,7 @@ public class ConstExpressionParser { } else if (op == TurbineOperatorKind.ASSIGN) { term1 = assign(term1, op); } else { - term1 = new Tree.Binary(term1, expression(op.prec()), op); + term1 = new Tree.Binary(position, term1, expression(op.prec()), op); } if (term1 == null) { return null; @@ -483,7 +486,7 @@ public class ConstExpressionParser { } String name = getOnlyElement(names); Tree.Expression rhs = expression(op.prec()); - return new Tree.Assign(name, rhs); + return new Tree.Assign(term1.position(), name, rhs); } private Tree.Expression ternary(Tree.Expression term1) { @@ -499,7 +502,7 @@ public class ConstExpressionParser { if (elseExpr == null) { return null; } - return new Tree.Conditional(term1, thenExpr, elseExpr); + return new Tree.Conditional(position, term1, thenExpr, elseExpr); } private Tree.Expression castTail(TurbineConstantTypeKind ty) { @@ -511,7 +514,7 @@ public class ConstExpressionParser { if (rhs == null) { throw new AssertionError(); } - return new Tree.TypeCast(new Tree.PrimTy(ty), rhs); + return new Tree.TypeCast(position, new Tree.PrimTy(position, ty), rhs); } private Tree.AnnoExpr annotation() { @@ -539,10 +542,10 @@ public class ConstExpressionParser { eat(); } } - return new Tree.AnnoExpr(new Tree.Anno(name, args.build())); + return new Tree.AnnoExpr(position, new Tree.Anno(position, name, args.build())); } - private ParseError error(Object message) { - return new ParseError(lexer.position(), String.valueOf(message)); + private TurbineError error(String message, Object... args) { + return TurbineError.format(lexer.source(), lexer.position(), message, args); } } diff --git a/java/com/google/turbine/parse/IteratorLexer.java b/java/com/google/turbine/parse/IteratorLexer.java index 04b8ab4..823f9bb 100644 --- a/java/com/google/turbine/parse/IteratorLexer.java +++ b/java/com/google/turbine/parse/IteratorLexer.java @@ -16,6 +16,7 @@ package com.google.turbine.parse; +import com.google.turbine.diag.SourceFile; import java.util.Iterator; /** @@ -25,14 +26,21 @@ import java.util.Iterator; */ public class IteratorLexer implements Lexer { + private final SourceFile source; private final Iterator<SavedToken> it; private SavedToken curr; - public IteratorLexer(Iterator<SavedToken> it) { + public IteratorLexer(SourceFile source, Iterator<SavedToken> it) { + this.source = source; this.it = it; } @Override + public SourceFile source() { + return source; + } + + @Override public Token next() { if (it.hasNext()) { curr = it.next(); @@ -48,6 +56,7 @@ public class IteratorLexer implements Lexer { @Override public int position() { - return curr.position; + // TODO(cushon): test expression position EOF handling + return curr != null ? curr.position : -1; } } diff --git a/java/com/google/turbine/parse/Lexer.java b/java/com/google/turbine/parse/Lexer.java index 58b092f..2d8422a 100644 --- a/java/com/google/turbine/parse/Lexer.java +++ b/java/com/google/turbine/parse/Lexer.java @@ -16,6 +16,8 @@ package com.google.turbine.parse; +import com.google.turbine.diag.SourceFile; + /** A Java lexer. */ public interface Lexer { /** Returns the next token in the input stream, or {@code EOF}. */ @@ -26,4 +28,7 @@ public interface Lexer { /** Returns the current position in the input. */ int position(); + + /** Returns the source file for diagnostics. */ + SourceFile source(); } diff --git a/java/com/google/turbine/parse/ParseError.java b/java/com/google/turbine/parse/ParseError.java deleted file mode 100644 index f3cc8fb..0000000 --- a/java/com/google/turbine/parse/ParseError.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.turbine.parse; - -/** A parse error. */ -public class ParseError extends Error { - private final int position; - - /** @param position the character offset of the parser error. */ - public ParseError(int position, String message) { - super(message); - this.position = position; - } - - /** Returns the UTF-16 code unit offset of the error. */ - public int position() { - return position; - } -} diff --git a/java/com/google/turbine/parse/Parser.java b/java/com/google/turbine/parse/Parser.java index 9025ef7..83d5e34 100644 --- a/java/com/google/turbine/parse/Parser.java +++ b/java/com/google/turbine/parse/Parser.java @@ -23,6 +23,8 @@ import static com.google.turbine.tree.TurbineModifier.PUBLIC; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; +import com.google.turbine.diag.SourceFile; +import com.google.turbine.diag.TurbineError; import com.google.turbine.model.TurbineConstantTypeKind; import com.google.turbine.model.TurbineTyKind; import com.google.turbine.tree.Tree; @@ -56,9 +58,14 @@ public class Parser { private final Lexer lexer; private Token token; + private int position; - public static CompUnit parse(String input) { - return new Parser(new StreamLexer(new UnicodeEscapePreprocessor(input))).compilationUnit(); + public static CompUnit parse(String source) { + return parse(new SourceFile(null, source)); + } + + public static CompUnit parse(SourceFile source) { + return new Parser(new StreamLexer(new UnicodeEscapePreprocessor(source))).compilationUnit(); } private Parser(Lexer lexer) { @@ -150,7 +157,7 @@ public class Parser { break; case EOF: // TODO(cushon): check for dangling modifiers? - return new CompUnit(pkg, imports.build(), decls.build(), null); + return new CompUnit(position, pkg, imports.build(), decls.build(), lexer.source()); case SEMI: // TODO(cushon): check for dangling modifiers? next(); @@ -163,6 +170,7 @@ public class Parser { private void next() { token = lexer.next(); + position = lexer.position(); } private TyDecl interfaceDeclaration(EnumSet<TurbineModifier> access, ImmutableList<Anno> annos) { @@ -185,6 +193,7 @@ public class Parser { ImmutableList<Tree> members = classMembers(); eat(Token.RBRACE); return new TyDecl( + position, access, annos, name, @@ -202,6 +211,7 @@ public class Parser { ImmutableList<Tree> members = classMembers(); eat(Token.RBRACE); return new TyDecl( + position, access, annos, name, @@ -227,6 +237,7 @@ public class Parser { ImmutableList.<Tree>builder().addAll(enumMembers(name)).addAll(classMembers()).build(); eat(Token.RBRACE); return new TyDecl( + position, access, annos, name, @@ -265,9 +276,11 @@ public class Parser { maybe(Token.COMMA); result.add( new VarDecl( + position, access, annos.build(), - new ClassTy(Optional.<ClassTy>absent(), enumName, ImmutableList.<Type>of()), + new ClassTy( + position, Optional.<ClassTy>absent(), enumName, ImmutableList.<Type>of()), name, Optional.<Expression>absent())); annos = ImmutableList.builder(); @@ -314,6 +327,7 @@ public class Parser { ImmutableList<Tree> members = classMembers(); eat(Token.RBRACE); return new TyDecl( + position, access, annos, name, @@ -451,7 +465,7 @@ public class Parser { switch (token) { case VOID: { - result = Tree.VoidTy.INSTANCE; + result = new Tree.VoidTy(position); next(); name = eatIdent(); return memberRest(access, annos, typaram, result, name); @@ -480,7 +494,9 @@ public class Parser { } case IDENT: { - result = new ClassTy(Optional.<ClassTy>absent(), ident, ImmutableList.<Type>of()); + result = + new ClassTy( + position, Optional.<ClassTy>absent(), ident, ImmutableList.<Type>of()); name = eatIdent(); return memberRest(access, annos, typaram, result, name); } @@ -494,26 +510,30 @@ public class Parser { } while (maybe(Token.LBRACK)); result = new ArrTy( - new ClassTy(Optional.<ClassTy>absent(), ident, ImmutableList.<Type>of()), + position, + new ClassTy( + position, Optional.<ClassTy>absent(), ident, ImmutableList.<Type>of()), dim); break; } case LT: { - Type ty = new ClassTy(Optional.<ClassTy>absent(), ident, tyargs()); + Type ty = new ClassTy(position, Optional.<ClassTy>absent(), ident, tyargs()); int dim = 0; while (maybe(Token.LBRACK)) { eat(Token.RBRACK); dim++; } if (dim > 0) { - ty = new ArrTy(ty, dim); + ty = new ArrTy(position, ty, dim); } result = ty; break; } case DOT: - result = new ClassTy(Optional.<ClassTy>absent(), ident, ImmutableList.<Type>of()); + result = + new ClassTy( + position, Optional.<ClassTy>absent(), ident, ImmutableList.<Type>of()); break; default: throw error(token); @@ -531,7 +551,7 @@ public class Parser { dim++; } if (dim > 0) { - result = new ArrTy(result, dim); + result = new ArrTy(position, result, dim); } } name = eatIdent(); @@ -544,7 +564,7 @@ public class Parser { case COMMA: { if (!typaram.isEmpty()) { - throw error(typaram); + throw error("%s", typaram); } return fieldRest(access, annos, result, name); } @@ -570,7 +590,7 @@ public class Parser { case COMMA: { if (!typaram.isEmpty()) { - throw error(typaram); + throw error("%s", typaram); } return fieldRest(access, annos, result, name); } @@ -600,7 +620,7 @@ public class Parser { if (next.token == Token.IDENT) { name = next.value; } else { - throw error(next); + throw error("%s", next); } } @@ -613,7 +633,7 @@ public class Parser { dim++; next = it.next(); if (next.token != Token.RBRACK) { - throw error(next); + throw error("%s", next); } if (it.hasNext()) { next = it.next(); @@ -622,11 +642,12 @@ public class Parser { newty = expandDims(ty, dim); } // TODO(cushon): skip more fields that are definitely non-const - Expression init = new ConstExpressionParser(new IteratorLexer(it)).expression(); + Expression init = + new ConstExpressionParser(new IteratorLexer(lexer.source(), it)).expression(); if (init != null && init.kind() == Tree.Kind.ARRAY_INIT) { init = null; } - result.add(new VarDecl(access, annos, newty, name, Optional.fromNullable(init))); + result.add(new VarDecl(position, access, annos, newty, name, Optional.fromNullable(init))); } eat(Token.SEMI); return result.build(); @@ -683,6 +704,7 @@ public class Parser { name = CTOR_NAME; } return new MethDecl( + position, access, annos, typaram, @@ -740,15 +762,15 @@ public class Parser { ty = parseDims(ty); } } - return new VarDecl(access, annos.build(), ty, name, Optional.<Expression>absent()); + return new VarDecl(position, access, annos.build(), ty, name, Optional.<Expression>absent()); } private Type expandDims(Type ty, int extra) { if (ty.kind() == Tree.Kind.ARR_TY) { Type.ArrTy aty = (Type.ArrTy) ty; - return new ArrTy(aty.elem(), aty.dim() + extra); + return new ArrTy(position, aty.elem(), aty.dim() + extra); } else if (extra > 0) { - return new ArrTy(ty, extra); + return new ArrTy(position, ty, extra); } else { return ty; } @@ -801,7 +823,7 @@ public class Parser { next(); bounds = tybounds(); } - acc.add(new TyParam(name, bounds)); + acc.add(new TyParam(position, name, bounds)); switch (token) { case COMMA: eat(Token.COMMA); @@ -829,13 +851,14 @@ public class Parser { } private ClassTy classty(ClassTy ty) { + int pos = position; do { String name = eatIdent(); ImmutableList<Type> tyargs = ImmutableList.of(); if (token == Token.LT) { tyargs = tyargs(); } - ty = new ClassTy(Optional.fromNullable(ty), name, tyargs); + ty = new ClassTy(pos, Optional.fromNullable(ty), name, tyargs); } while (maybe(Token.DOT)); return ty; } @@ -853,20 +876,20 @@ public class Parser { case EXTENDS: next(); Type upper = referenceType(); - acc.add(new WildTy(Optional.of(upper), Optional.<Type>absent())); + acc.add(new WildTy(position, Optional.of(upper), Optional.<Type>absent())); break; case SUPER: next(); Type lower = referenceType(); - acc.add(new WildTy(Optional.<Type>absent(), Optional.of(lower))); + acc.add(new WildTy(position, Optional.<Type>absent(), Optional.of(lower))); break; case COMMA: - acc.add(new WildTy(Optional.<Type>absent(), Optional.<Type>absent())); + acc.add(new WildTy(position, Optional.<Type>absent(), Optional.<Type>absent())); continue OUTER; case GT: case GTGT: case GTGTGT: - acc.add(new WildTy(Optional.<Type>absent(), Optional.<Type>absent())); + acc.add(new WildTy(position, Optional.<Type>absent(), Optional.<Type>absent())); break OUTER; default: throw error(token); @@ -912,35 +935,35 @@ public class Parser { break; case BOOLEAN: next(); - ty = new PrimTy(TurbineConstantTypeKind.BOOLEAN); + ty = new PrimTy(position, TurbineConstantTypeKind.BOOLEAN); break; case BYTE: next(); - ty = new PrimTy(TurbineConstantTypeKind.BYTE); + ty = new PrimTy(position, TurbineConstantTypeKind.BYTE); break; case SHORT: next(); - ty = new PrimTy(TurbineConstantTypeKind.SHORT); + ty = new PrimTy(position, TurbineConstantTypeKind.SHORT); break; case INT: next(); - ty = new PrimTy(TurbineConstantTypeKind.INT); + ty = new PrimTy(position, TurbineConstantTypeKind.INT); break; case LONG: next(); - ty = new PrimTy(TurbineConstantTypeKind.LONG); + ty = new PrimTy(position, TurbineConstantTypeKind.LONG); break; case CHAR: next(); - ty = new PrimTy(TurbineConstantTypeKind.CHAR); + ty = new PrimTy(position, TurbineConstantTypeKind.CHAR); break; case DOUBLE: next(); - ty = new PrimTy(TurbineConstantTypeKind.DOUBLE); + ty = new PrimTy(position, TurbineConstantTypeKind.DOUBLE); break; case FLOAT: next(); - ty = new PrimTy(TurbineConstantTypeKind.FLOAT); + ty = new PrimTy(position, TurbineConstantTypeKind.FLOAT); break; default: throw error(token); @@ -951,7 +974,7 @@ public class Parser { dim++; } if (dim > 0) { - ty = new ArrTy(ty, dim); + ty = new ArrTy(position, ty, dim); } return ty; } @@ -1035,11 +1058,11 @@ public class Parser { } } eat(Token.SEMI); - return new ImportDecl(type.build(), stat, wild); + return new ImportDecl(position, type.build(), stat, wild); } private PkgDecl packageDeclaration() { - PkgDecl result = new PkgDecl(qualIdent()); + PkgDecl result = new PkgDecl(position, qualIdent()); eat(Token.SEMI); return result; } @@ -1066,7 +1089,7 @@ public class Parser { eat(Token.RPAREN); } - return new Anno(name, args.build()); + return new Anno(position, name, args.build()); } private String eatIdent() { @@ -1090,7 +1113,7 @@ public class Parser { return false; } - ParseError error(Token token) { + TurbineError error(Token token) { String message; switch (token) { case IDENT: @@ -1100,10 +1123,10 @@ public class Parser { message = String.format("unexpected token %s", token); break; } - return new ParseError(lexer.position(), message); + return TurbineError.format(lexer.source(), lexer.position(), message, new Object[] {}); } - private ParseError error(Object message) { - return new ParseError(lexer.position(), String.valueOf(message)); + private TurbineError error(String message, Object... args) { + return TurbineError.format(lexer.source(), lexer.position(), message, args); } } diff --git a/java/com/google/turbine/parse/StreamLexer.java b/java/com/google/turbine/parse/StreamLexer.java index cc6d6c2..35dd81d 100644 --- a/java/com/google/turbine/parse/StreamLexer.java +++ b/java/com/google/turbine/parse/StreamLexer.java @@ -19,6 +19,8 @@ package com.google.turbine.parse; import static com.google.turbine.parse.UnicodeEscapePreprocessor.ASCII_SUB; import com.google.common.base.Verify; +import com.google.turbine.diag.SourceFile; +import com.google.turbine.diag.TurbineError; /** A {@link Lexer} that streams input from a {@link UnicodeEscapePreprocessor}. */ public class StreamLexer implements Lexer { @@ -28,6 +30,9 @@ public class StreamLexer implements Lexer { /** The current input character. */ private char ch; + /** The start position of the current token. */ + private int position; + /** The start position of the current numeric literal or identifier token. */ private int readFrom; @@ -65,15 +70,19 @@ public class StreamLexer implements Lexer { @Override public int position() { - // TODO(cushon): this is the position of the character after the last token that was lexed, - // keep track of start positions instead. - return reader.position(); + return position; + } + + @Override + public SourceFile source() { + return reader.source(); } @Override public Token next() { OUTER: while (true) { + position = reader.position(); switch (ch) { case '\r': case '\n': @@ -309,8 +318,7 @@ public class StreamLexer implements Lexer { eat(); return Token.ELLIPSIS; } else { - throw new ParseError( - reader.position(), String.format("unexpected input: %c", ch)); + throw error("unexpected input: %c", ch); } } case '0': @@ -345,7 +353,7 @@ public class StreamLexer implements Lexer { eat(); return Token.CHAR_LITERAL; } - throw new ParseError(reader.position(), String.format("unexpected input: %c", ch)); + throw error("unexpected input: %c", ch); } case '"': @@ -379,7 +387,7 @@ public class StreamLexer implements Lexer { } // does not fall through default: - throw new ParseError(reader.position(), String.format("unexpected input: %c", ch)); + throw error("unexpected input: %c", ch); } } } @@ -459,7 +467,7 @@ public class StreamLexer implements Lexer { } } default: - throw new ParseError(reader.position(), String.format("unexpected input: %c", ch)); + throw error("unexpected input: %c", ch); } } @@ -566,7 +574,7 @@ public class StreamLexer implements Lexer { eat(); break; default: - throw new ParseError(reader.position(), String.format("unexpected input: %c", ch)); + throw error("unexpected input: %c", ch); } OUTER: while (true) { @@ -601,7 +609,7 @@ public class StreamLexer implements Lexer { case '9': continue OUTER; default: - throw new ParseError(reader.position(), String.format("unexpected input: %c", ch)); + throw error("unexpected input: %c", ch); } } case 'A': @@ -638,7 +646,7 @@ public class StreamLexer implements Lexer { if ('0' <= ch && ch <= '9') { eat(); } else { - throw new ParseError(reader.position(), String.format("unexpected input: %c", ch)); + throw error("unexpected input: %c", ch); } OUTER: while (true) { @@ -650,7 +658,7 @@ public class StreamLexer implements Lexer { if ('0' <= ch && ch <= '9') { continue OUTER; } else { - throw new ParseError(reader.position(), String.format("unexpected input: %c", ch)); + throw error("unexpected input: %c", ch); } case '0': case '1': @@ -689,7 +697,7 @@ public class StreamLexer implements Lexer { eat(); break; default: - throw new ParseError(reader.position(), String.format("unexpected input: %c", ch)); + throw error("unexpected input: %c", ch); } OUTER: while (true) { @@ -703,7 +711,7 @@ public class StreamLexer implements Lexer { case '1': continue OUTER; default: - throw new ParseError(reader.position(), String.format("unexpected input: %c", ch)); + throw error("unexpected input: %c", ch); } case '0': case '1': @@ -740,7 +748,7 @@ public class StreamLexer implements Lexer { eat(); break; default: - throw new ParseError(reader.position(), String.format("unexpected input: %c", ch)); + throw error("unexpected input: %c", ch); } OUTER: while (true) { @@ -760,7 +768,7 @@ public class StreamLexer implements Lexer { case '7': continue OUTER; default: - throw new ParseError(reader.position(), String.format("unexpected input: %c", ch)); + throw error("unexpected input: %c", ch); } case '0': case '1': @@ -934,7 +942,7 @@ public class StreamLexer implements Lexer { } case '/': // handled with comments - throw new ParseError(reader.position(), String.format("unexpected input: %c", ch)); + throw error("unexpected input: %c", ch); case '%': eat(); @@ -953,7 +961,7 @@ public class StreamLexer implements Lexer { return Token.XOR; } default: - throw new ParseError(reader.position(), String.format("unexpected input: %c", ch)); + throw error("unexpected input: %c", ch); } } @@ -1146,4 +1154,8 @@ public class StreamLexer implements Lexer { return Token.IDENT; } } + + private TurbineError error(String message, Object... args) { + return TurbineError.format(reader.source(), reader.position(), message, args); + } } diff --git a/java/com/google/turbine/parse/UnicodeEscapePreprocessor.java b/java/com/google/turbine/parse/UnicodeEscapePreprocessor.java index 92eef55..2bbd897 100644 --- a/java/com/google/turbine/parse/UnicodeEscapePreprocessor.java +++ b/java/com/google/turbine/parse/UnicodeEscapePreprocessor.java @@ -16,19 +16,24 @@ package com.google.turbine.parse; +import com.google.turbine.diag.SourceFile; +import com.google.turbine.diag.TurbineError; + /** Preprocesses Unicode escape characters in Java source code, as described in JLS ยง3.3. */ public class UnicodeEscapePreprocessor { public static final char ASCII_SUB = 0x1A; + private final SourceFile source; private final String input; private int idx = 0; private char ch; private boolean evenLeadingSlashes = true; - public UnicodeEscapePreprocessor(String input) { - this.input = input; + public UnicodeEscapePreprocessor(SourceFile source) { + this.source = source; + this.input = source.source(); } /** Returns the current position in the input. */ @@ -109,9 +114,9 @@ public class UnicodeEscapePreprocessor { case 'f': return ((d - 'a') + 10); case ASCII_SUB: - throw new ParseError(position(), "unexpected end of input"); + throw new AssertionError("unexpected end of input"); default: - throw new ParseError(position(), String.format("0x%x", (int) d)); + throw TurbineError.format(source, position(), "0x%x", (int) d); } } @@ -126,4 +131,8 @@ public class UnicodeEscapePreprocessor { ch = done() ? ASCII_SUB : input.charAt(idx); idx++; } + + public SourceFile source() { + return source; + } } |