Mercurial > projects > dang
view parser/Action.d @ 46:90fb4fdfefdd new_gen
While is back
author | Anders Halager <halager@gmail.com> |
---|---|
date | Wed, 23 Apr 2008 17:01:24 +0200 |
parents | 9bc660cbdbec |
children | b6c1dc30ca4b |
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 { 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; } /** 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 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; } } /** 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(cast(Stmt[])array); } 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); } // -- 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; 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); } }