Mercurial > projects > dang
diff parser/Action.d @ 44:495188f9078e new_gen
Big update - Moving towards a better, more seperated parser
The parser no loner creates the AST directly, but through
callbacks(actions). This means the parser can be run with a different set
of actions that do something else.
The parser is not back to full strength yet, the main thing missing is the
various statements and structs.
Also added a SmallArray that uses the stack only until a given size is
exceeded, after which the array is copied unto the heap.
author | Anders Halager <halager@gmail.com> |
---|---|
date | Wed, 23 Apr 2008 00:57:45 +0200 |
parents | |
children | 9bc660cbdbec |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/parser/Action.d Wed Apr 23 00:57:45 2008 +0200 @@ -0,0 +1,267 @@ +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 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 +{ + 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; + } + + override StmtT actOnCompoundStmt(ref Token l, ref Token r, StmtT[] stmts) + { + StmtT[] array = stmts.dup; + Stmt[] statements = cast(Stmt[])array; + Stdout(statements).newline; + 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 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); + } +} +