📄 checker.java
字号:
ast.T = (TypeDenoter) ast.T.visit(this, null);
ast.FT.visit(this, null);
return ast;
}
public Object visitSingleFieldTypeDenoter(SingleFieldTypeDenoter ast, Object o) {
ast.T = (TypeDenoter) ast.T.visit(this, null);
return ast;
}
// Literals, Identifiers and Operators
public Object visitCharacterLiteral(CharacterLiteral CL, Object o) {
return StdEnvironment.charType;
}
public Object visitIdentifier(Identifier I, Object o) {
Declaration binding = idTable.retrieve(I.spelling);
if (binding != null)
I.decl = binding;
return binding;
}
public Object visitIntegerLiteral(IntegerLiteral IL, Object o) {
return StdEnvironment.integerType;
}
public Object visitOperator(Operator O, Object o) {
Declaration binding = idTable.retrieve(O.spelling);
if (binding != null)
O.decl = binding;
return binding;
}
// Value-or-variable names
// Determines the address of a named object (constant or variable).
// This consists of a base object, to which 0 or more field-selection
// or array-indexing operations may be applied (if it is a record or
// array). As much as possible of the address computation is done at
// compile-time. Code is generated only when necessary to evaluate
// index expressions at run-time.
// currentLevel is the routine level where the v-name occurs.
// frameSize is the anticipated size of the local stack frame when
// the object is addressed at run-time.
// It returns the description of the base object.
// offset is set to the total of any field offsets (plus any offsets
// due to index expressions that happen to be literals).
// indexed is set to true iff there are any index expressions (other
// than literals). In that case code is generated to compute the
// offset due to these indexing operations at run-time.
// Returns the TypeDenoter of the Vname. Does not use the
// given object.
public Object visitDotVname(DotVname ast, Object o) {
ast.type = null;
TypeDenoter vType = (TypeDenoter) ast.V.visit(this, null);
ast.variable = ast.V.variable;
if (! (vType instanceof RecordTypeDenoter))
reporter.reportError ("record expected here", "", ast.V.position);
else {
ast.type = checkFieldIdentifier(((RecordTypeDenoter) vType).FT, ast.I);
if (ast.type == StdEnvironment.errorType)
reporter.reportError ("no field \"%\" in this record type",
ast.I.spelling, ast.I.position);
}
return ast.type;
}
public Object visitSimpleVname(SimpleVname ast, Object o) {
ast.variable = false;
ast.type = StdEnvironment.errorType;
Declaration binding = (Declaration) ast.I.visit(this, null);
if (binding == null)
reportUndeclared(ast.I);
else
if (binding instanceof ConstDeclaration) {
ast.type = ((ConstDeclaration) binding).E.type;
ast.variable = false;
} else if (binding instanceof VarDeclaration) {
ast.type = ((VarDeclaration) binding).T;
ast.variable = true;
} else if (binding instanceof ConstFormalParameter) {
ast.type = ((ConstFormalParameter) binding).T;
ast.variable = false;
} else if (binding instanceof VarFormalParameter) {
ast.type = ((VarFormalParameter) binding).T;
ast.variable = true;
} else
reporter.reportError ("\"%\" is not a const or var identifier",
ast.I.spelling, ast.I.position);
return ast.type;
}
public Object visitSubscriptVname(SubscriptVname ast, Object o) {
TypeDenoter vType = (TypeDenoter) ast.V.visit(this, null);
ast.variable = ast.V.variable;
TypeDenoter eType = (TypeDenoter) ast.E.visit(this, null);
if (vType != StdEnvironment.errorType) {
if (! (vType instanceof ArrayTypeDenoter))
reporter.reportError ("array expected here", "", ast.V.position);
else {
if (! eType.equals(StdEnvironment.integerType))
reporter.reportError ("Integer expression expected here", "",
ast.E.position);
ast.type = ((ArrayTypeDenoter) vType).T;
}
}
return ast.type;
}
// Programs
public Object visitProgram(Program ast, Object o) {
ast.C.visit(this, null);
return null;
}
// Checks whether the source program, represented by its AST, satisfies the
// language's scope rules and type rules.
// Also decorates the AST as follows:
// (a) Each applied occurrence of an identifier or operator is linked to
// the corresponding declaration of that identifier or operator.
// (b) Each expression and value-or-variable-name is decorated by its type.
// (c) Each type identifier is replaced by the type it denotes.
// Types are represented by small ASTs.
public void check(Program ast) {
ast.visit(this, null);
}
/////////////////////////////////////////////////////////////////////////////
public Checker (ErrorReporter reporter) {
this.reporter = reporter;
this.idTable = new IdentificationTable ();
establishStdEnvironment();
}
private IdentificationTable idTable;
private static SourcePosition dummyPos = new SourcePosition();
private ErrorReporter reporter;
// Reports that the identifier or operator used at a leaf of the AST
// has not been declared.
private void reportUndeclared (Terminal leaf) {
reporter.reportError("\"%\" is not declared", leaf.spelling, leaf.position);
}
private static TypeDenoter checkFieldIdentifier(FieldTypeDenoter ast, Identifier I) {
if (ast instanceof MultipleFieldTypeDenoter) {
MultipleFieldTypeDenoter ft = (MultipleFieldTypeDenoter) ast;
if (ft.I.spelling.compareTo(I.spelling) == 0) {
I.decl = ast;
return ft.T;
} else {
return checkFieldIdentifier (ft.FT, I);
}
} else if (ast instanceof SingleFieldTypeDenoter) {
SingleFieldTypeDenoter ft = (SingleFieldTypeDenoter) ast;
if (ft.I.spelling.compareTo(I.spelling) == 0) {
I.decl = ast;
return ft.T;
}
}
return StdEnvironment.errorType;
}
// Creates a small AST to represent the "declaration" of a standard
// type, and enters it in the identification table.
private TypeDeclaration declareStdType (String id, TypeDenoter typedenoter) {
TypeDeclaration binding;
binding = new TypeDeclaration(new Identifier(id, dummyPos), typedenoter, dummyPos);
idTable.enter(id, binding);
return binding;
}
// Creates a small AST to represent the "declaration" of a standard
// type, and enters it in the identification table.
private ConstDeclaration declareStdConst (String id, TypeDenoter constType) {
IntegerExpression constExpr;
ConstDeclaration binding;
// constExpr used only as a placeholder for constType
constExpr = new IntegerExpression(null, dummyPos);
constExpr.type = constType;
binding = new ConstDeclaration(new Identifier(id, dummyPos), constExpr, dummyPos);
idTable.enter(id, binding);
return binding;
}
// Creates a small AST to represent the "declaration" of a standard
// type, and enters it in the identification table.
private ProcDeclaration declareStdProc (String id, FormalParameterSequence fps) {
ProcDeclaration binding;
binding = new ProcDeclaration(new Identifier(id, dummyPos), fps,
new EmptyCommand(dummyPos), dummyPos);
idTable.enter(id, binding);
return binding;
}
// Creates a small AST to represent the "declaration" of a standard
// type, and enters it in the identification table.
private FuncDeclaration declareStdFunc (String id, FormalParameterSequence fps,
TypeDenoter resultType) {
FuncDeclaration binding;
binding = new FuncDeclaration(new Identifier(id, dummyPos), fps, resultType,
new EmptyExpression(dummyPos), dummyPos);
idTable.enter(id, binding);
return binding;
}
// Creates a small AST to represent the "declaration" of a
// unary operator, and enters it in the identification table.
// This "declaration" summarises the operator's type info.
private UnaryOperatorDeclaration declareStdUnaryOp
(String op, TypeDenoter argType, TypeDenoter resultType) {
UnaryOperatorDeclaration binding;
binding = new UnaryOperatorDeclaration (new Operator(op, dummyPos),
argType, resultType, dummyPos);
idTable.enter(op, binding);
return binding;
}
// Creates a small AST to represent the "declaration" of a
// binary operator, and enters it in the identification table.
// This "declaration" summarises the operator's type info.
private BinaryOperatorDeclaration declareStdBinaryOp
(String op, TypeDenoter arg1Type, TypeDenoter arg2type, TypeDenoter resultType) {
BinaryOperatorDeclaration binding;
binding = new BinaryOperatorDeclaration (new Operator(op, dummyPos),
arg1Type, arg2type, resultType, dummyPos);
idTable.enter(op, binding);
return binding;
}
// Creates small ASTs to represent the standard types.
// Creates small ASTs to represent "declarations" of standard types,
// constants, procedures, functions, and operators.
// Enters these "declarations" in the identification table.
private final static Identifier dummyI = new Identifier("", dummyPos);
private void establishStdEnvironment () {
// idTable.startIdentification();
StdEnvironment.booleanType = new BoolTypeDenoter(dummyPos);
StdEnvironment.integerType = new IntTypeDenoter(dummyPos);
StdEnvironment.charType = new CharTypeDenoter(dummyPos);
StdEnvironment.anyType = new AnyTypeDenoter(dummyPos);
StdEnvironment.errorType = new ErrorTypeDenoter(dummyPos);
StdEnvironment.booleanDecl = declareStdType("Boolean", StdEnvironment.booleanType);
StdEnvironment.falseDecl = declareStdConst("false", StdEnvironment.booleanType);
StdEnvironment.trueDecl = declareStdConst("true", StdEnvironment.booleanType);
StdEnvironment.notDecl = declareStdUnaryOp("\\", StdEnvironment.booleanType, StdEnvironment.booleanType);
StdEnvironment.andDecl = declareStdBinaryOp("/\\", StdEnvironment.booleanType, StdEnvironment.booleanType, StdEnvironment.booleanType);
StdEnvironment.orDecl = declareStdBinaryOp("\\/", StdEnvironment.booleanType, StdEnvironment.booleanType, StdEnvironment.booleanType);
StdEnvironment.integerDecl = declareStdType("Integer", StdEnvironment.integerType);
StdEnvironment.maxintDecl = declareStdConst("maxint", StdEnvironment.integerType);
StdEnvironment.addDecl = declareStdBinaryOp("+", StdEnvironment.integerType, StdEnvironment.integerType, StdEnvironment.integerType);
StdEnvironment.subtractDecl = declareStdBinaryOp("-", StdEnvironment.integerType, StdEnvironment.integerType, StdEnvironment.integerType);
StdEnvironment.multiplyDecl = declareStdBinaryOp("*", StdEnvironment.integerType, StdEnvironment.integerType, StdEnvironment.integerType);
StdEnvironment.divideDecl = declareStdBinaryOp("/", StdEnvironment.integerType, StdEnvironment.integerType, StdEnvironment.integerType);
StdEnvironment.moduloDecl = declareStdBinaryOp("//", StdEnvironment.integerType, StdEnvironment.integerType, StdEnvironment.integerType);
StdEnvironment.lessDecl = declareStdBinaryOp("<", StdEnvironment.integerType, StdEnvironment.integerType, StdEnvironment.booleanType);
StdEnvironment.notgreaterDecl = declareStdBinaryOp("<=", StdEnvironment.integerType, StdEnvironment.integerType, StdEnvironment.booleanType);
StdEnvironment.greaterDecl = declareStdBinaryOp(">", StdEnvironment.integerType, StdEnvironment.integerType, StdEnvironment.booleanType);
StdEnvironment.notlessDecl = declareStdBinaryOp(">=", StdEnvironment.integerType, StdEnvironment.integerType, StdEnvironment.booleanType);
StdEnvironment.charDecl = declareStdType("Char", StdEnvironment.charType);
StdEnvironment.chrDecl = declareStdFunc("chr", new SingleFormalParameterSequence(
new ConstFormalParameter(dummyI, StdEnvironment.integerType, dummyPos), dummyPos), StdEnvironment.charType);
StdEnvironment.ordDecl = declareStdFunc("ord", new SingleFormalParameterSequence(
new ConstFormalParameter(dummyI, StdEnvironment.charType, dummyPos), dummyPos), StdEnvironment.integerType);
StdEnvironment.eofDecl = declareStdFunc("eof", new EmptyFormalParameterSequence(dummyPos), StdEnvironment.booleanType);
StdEnvironment.eolDecl = declareStdFunc("eol", new EmptyFormalParameterSequence(dummyPos), StdEnvironment.booleanType);
StdEnvironment.getDecl = declareStdProc("get", new SingleFormalParameterSequence(
new VarFormalParameter(dummyI, StdEnvironment.charType, dummyPos), dummyPos));
StdEnvironment.putDecl = declareStdProc("put", new SingleFormalParameterSequence(
new ConstFormalParameter(dummyI, StdEnvironment.charType, dummyPos), dummyPos));
StdEnvironment.getintDecl = declareStdProc("getint", new SingleFormalParameterSequence(
new VarFormalParameter(dummyI, StdEnvironment.integerType, dummyPos), dummyPos));
StdEnvironment.putintDecl = declareStdProc("putint", new SingleFormalParameterSequence(
new ConstFormalParameter(dummyI, StdEnvironment.integerType, dummyPos), dummyPos));
StdEnvironment.geteolDecl = declareStdProc("geteol", new EmptyFormalParameterSequence(dummyPos));
StdEnvironment.puteolDecl = declareStdProc("puteol", new EmptyFormalParameterSequence(dummyPos));
StdEnvironment.equalDecl = declareStdBinaryOp("=", StdEnvironment.anyType, StdEnvironment.anyType, StdEnvironment.booleanType);
StdEnvironment.unequalDecl = declareStdBinaryOp("\\=", StdEnvironment.anyType, StdEnvironment.anyType, StdEnvironment.booleanType);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -