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);
+    }
+}
+