Mercurial > projects > dang
view parser/Action.d @ 48:b6c1dc30ca4b new_gen
Only tests that dont pass now are structs and switches
As far as the parser is concerned assignments are binary expressions
Fixed a bug in codegen of if's - it is important to remember that the
builder might be positioned at a new block after generating sub-statements
author | Anders Halager <halager@gmail.com> |
---|---|
date | Thu, 24 Apr 2008 19:42:53 +0200 |
parents | 90fb4fdfefdd |
children | c7cde6af0095 |
line wrap: on
line source
module parser.Action; import lexer.Token; import ast.Exp, ast.Stmt, ast.Decl; import misc.Error; import tango.io.Stdout, Integer = tango.text.convert.Integer; /** Used to indicate what type of operator is used in a given binary expression (and unary expressions?) */ public enum Operator { Assign, Eq, Ne, Lt, Le, Gt, Ge, Add, Sub, Mul, Div, Mod, } struct Id { Token tok; char[] toString() { return tok.get; } } /** All methods are optional. Warning: Interface is not stable yet. Use the `override` keyword in all classes inheriting from this to get warning if the interface changes. */ abstract class Action { /** A few aliases to indicate what methods should be dealing with the same types. Not typesafe, and not using typedef because users would need a lot of casts (and base type would be void*, so no possibility to synchronize, print etc.) */ alias Object ExprT; alias Object StmtT; /// ditto alias Object DeclT; /// ditto // -- Declarations -- /** Either we should have one case that handles a lot of things, or we should have a lot of separate cases. As an example, this method could handle the params in `int f(int, int)` as well as handling `int x` at both top-level, in classes and in methods. The other solution is an addParamToFunc or similar. */ DeclT actOnDeclarator(ref Id type, ref Id name, ExprT init) { return null; } /** Add an initialization expression to a previously created decl. Used for default values on function params and for values to local variables. */ void addInitToDeclarator(DeclT decl, ExprT exp) { } /** Called at the start of a function, doesn't get a lot of info - that is added later on, through addFuncArg and actOnEndOfFunction. */ DeclT actOnStartOfFunctionDef(ref Id type, ref Id name) { return null; } /** Add a new parameter to the function func. */ void addFuncArg(DeclT func, Id type, Id name) { } /** Finish off the function, by giving it the body (a single statement, so you probably want some sort of compound statement) */ DeclT actOnEndOfFunction(DeclT func, StmtT stmts) { return func; } // -- Statements -- /** Called after parsing a function/while/for/whatever body. Note that stmts is to be considered temporary, it might point into the stack and needs to be copied before saving. */ StmtT actOnCompoundStmt(ref Token left, ref Token right, StmtT[] stmts) { return null; } /** An expression was used as a statement - this includes assignments, function calls. Additionally the D spec dictates that expressions with no effect are not legal as statements, but the parser can't test for this so it has to be done in the later stages. */ StmtT actOnExprStmt(ExprT exp) { return null; } /** Called after parsing return statements. loc is the return token. */ StmtT actOnReturnStmt(ref Token loc, ExprT exp) { return null; } /** */ StmtT actOnIfStmt(ref Token ifTok, ExprT cond, StmtT thenBody, ref Token elseTok, StmtT elseBody) { return null; } /** */ StmtT actOnWhileStmt(ref Token whileTok, ExprT cond, StmtT whileBody) { return null; } /** */ StmtT actOnDeclStmt(DeclT decl) { return null; } StmtT actOnStartOfSwitchStmt() { return null; } void actOnCaseStmt() { } void actOnDefaultStmt() { } StmtT actOnFinishSwitchStmt(StmtT sw) { return sw; } // -- Expressions -- /** A single numerical constant -- this can be absolutely any kind of number. Integers, floats, hex, octal, binary, imaginary and so on. */ ExprT actOnNumericConstant(Token op) { return null; } /** This is called when identifiers are used in expressions. */ ExprT actOnIdentifierExp(Id id) { return null; } /** Unary operator. */ ExprT actOnUnaryOp(Token op, ExprT operand) { return null; } /** Binary operator. */ ExprT actOnBinaryOp(Operator op, ExprT l, ExprT r) { return null; } /** Called when using the 'dot' operator. The left hand side can be any expression, but its only possible to look up an identifier. */ ExprT actOnMemberReference(ExprT lhs, Location op, Id member) { return null; } /** Called when function calls are encountered. Note that args is temporary and might point into the stack. Remember to copy before saving a reference to it. */ ExprT actOnCallExpr(ExprT func, ref Token left_paren, ExprT[] args, ref Token right_paren) { return null; } } /** This class implements the default actions for Dang, by building up an AST with the data needed in a compiler. */ class AstAction : Action { // -- Declarations -- override DeclT actOnDeclarator(ref Id type, ref Id id, ExprT init) { Exp exp = cast(Exp)init; return new VarDecl(new Identifier(type.tok), new Identifier(id.tok), exp); } override DeclT actOnStartOfFunctionDef(ref Id type, ref Id name) { return new FuncDecl(new Identifier(type.tok), new Identifier(name.tok)); } override void addFuncArg(DeclT func, Id type, Id name) { FuncDecl fd = cast(FuncDecl)func; fd.addParam(new Identifier(type.tok), new Identifier(name.tok)); } override DeclT actOnEndOfFunction(DeclT func, StmtT stmts) { FuncDecl fd = cast(FuncDecl)func; fd.setBody(cast(CompoundStatement)stmts); return fd; } // -- Statements -- override StmtT actOnCompoundStmt(ref Token l, ref Token r, StmtT[] stmts) { StmtT[] array = stmts.dup; Stmt[] statements = cast(Stmt[])array; return new CompoundStatement(statements); } override StmtT actOnExprStmt(ExprT exp) { return new ExpStmt(cast(Exp)exp); } override StmtT actOnReturnStmt(ref Token loc, ExprT exp) { Exp e = cast(Exp)exp; auto res = new ReturnStmt; res.exp = e; return res; } override StmtT actOnIfStmt(ref Token ifTok, ExprT cond, StmtT thenBody, ref Token elseTok, StmtT elseBody) { Exp c = cast(Exp)cond; Stmt t = cast(Stmt)thenBody; Stmt e = cast(Stmt)elseBody; return new IfStmt(c, t, e); } override StmtT actOnWhileStmt(ref Token tok, ExprT cond, StmtT whileBody) { Exp c = cast(Exp)cond; Stmt b = cast(Stmt)whileBody; return new WhileStmt(c, b); } override StmtT actOnDeclStmt(DeclT decl) { Decl d = cast(Decl)decl; return new DeclStmt(d); } // -- Expressions -- override ExprT actOnNumericConstant(Token c) { return new IntegerLit(c); } override ExprT actOnIdentifierExp(Id id) { return new Identifier(id.tok); } override ExprT actOnBinaryOp(Operator op, ExprT l, ExprT r) { Exp left = cast(Exp)l; Exp right = cast(Exp)r; if (op == Operator.Assign) return new AssignExp(left, right); else return new BinaryExp(cast(BinaryExp.Operator)op, left, right); } override ExprT actOnUnaryOp(Token op, ExprT operand) { Exp target = cast(Exp)operand; // can only be -x for now return new NegateExp(target); } override ExprT actOnCallExpr(ExprT fn, ref Token, ExprT[] args, ref Token) { Exp f = cast(Exp)fn; Exp[] arguments = cast(Exp[])args.dup; return new CallExp(f, arguments); } }