view src/parser/Action.d @ 209:42e663451371

Renamed some of the actions. Declarations now have it's own action.
author Anders Johnsen <skabet@gmail.com>
date Tue, 12 Aug 2008 19:05:17 +0200
parents e0551773a005
children
line wrap: on
line source

module parser.Action;

import lexer.Token;

import basic.Attribute;

/**
  Used to indicate what type of operator is used in a given binary expression
  (and unary expressions?)
 */
public enum Operator
{
    Assign,
    AddAssign,
    SubAssign,
    MulAssign,
    DivAssign,
    ModAssign,

    Eq, Ne,

    Lt, Le,
    Gt, Ge,

    Add, Sub,
    Mul, Div, Mod,

    LeftShift, RightShift, UnsignedRightShift,
}


class Id
{
    public static Id opCall(Token tok)
    {
        auto id = new Id();
        id.tok = tok;
        return id;
    }
    Token tok;
}

class PointerTypeId : Id
{
    public static PointerTypeId opCall(Id id)
    {
        auto p = new PointerTypeId();
        p.id = id;
        return p;
    }

    Id id;
}

class StaticArrayTypeId : Id
{
    public static StaticArrayTypeId opCall(Id id, Object number)
    {
        auto a = new StaticArrayTypeId();
        a.id = id;
        a.number = number;
        return a;
    }

    Id id;
    Object number;
}

class FunctionTypeId : Id
{
    public static FunctionTypeId opCall(Id id, DeclT[] decls)
    {
        auto f = new FunctionTypeId();
        f.id = id;
        f.decls = decls;
        return f;
    }

    Id id;
    DeclT[] decls;
}

/**
  Represents a fully qualified name, with some packages and a final identifier.
  The identifier should always be set, but packages may have length 0.
 **/
struct ModuleName
{
    Id id;
    Id[] packages;

    /// Get the full ranged spanned by packages and identifier
    SourceRange asRange()
    {
        SourceRange r = id.tok.asRange();
        foreach (identifier; packages)
            r = r + identifier.tok.asRange();
        return r;
    }
}

    /**
      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
alias Object ModuleT; /// ditto

/**
  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
{


    // -- Modules --

    ModuleT actOnModule(ref Token _module, char[] name)
    {
        return null;
    }

    /**
      This action is called when a file does not start with a module
      declaration - in which case there is no Token available.

      Instead a SLoc to the start of the file is given.
     */
    ModuleT actOnImplicitModule(SourceLocation fileStart, char[] name)
    {
        return null;
    }

    void actOnModuleDecl(ModuleT m, DeclT d)
    {
    }

    // -- Declarations --

    /**
      Called for an import statement, that may be renamed. Id name is null,
      there is no rename.

      If there are selective imports, its handled in add 
     */
    DeclT actOnImport(ref Token _import, ref ModuleName target, Id* name)
    {
        return null;
    }

    /**
     */
    void addSelectiveImport(DeclT _import, ref Id target, Id* name)
    {
    }

    /**
      Called when an simple variable had been parsed.
     */
    DeclT actOnVarDecl(ref Id type, ref Id name, 
            ExprT initializer, Attribute att)
    {
        return null;
    }

    /**
      Called when a struct has been parsed. 

      actOnStructMember will be called for all members
     */
    DeclT actOnStructDecl(ref Id name, Attribute att)
    {
        return null;
    }

    /**
      Called when a class has been parsed. 

      actOnClassMember will be called for all members
      actOnClassBaseClass will be called for all base classes
     */
    DeclT actOnClassDecl(ref Id name, Attribute att)
    {
        return null;
    }

    /**
      Called when a interface has been parsed. 

      actOnInterfaceMember will be called for all members
      actOnInterfaceBaseClass will be called for all base classes
     */
    DeclT actOnInterfaceDecl(ref Id name, Attribute att)
    {
        return null;
    }

    DeclT actOnAliasDecl(DeclT decl, Attribute att)
    {
        return null;
    }

    /**
      Add a struct member to a struct.
     */
    void actOnStructMember(DeclT st_decl, DeclT m_decl)
    {
        return null;
    }

    /**
      Add a class member to a struct.
     */
    void actOnClassMember(DeclT cl_decl, DeclT m_decl)
    {
        return null;
    }

    /**
      Add a class member to a struct.
     */
    void actOnClassBaseClass(DeclT cl_decl, ref Id name)
    {
        return null;
    }

    /**
      Add a class member to a struct.
     */
    void actOnInterfaceMember(DeclT if_decl, DeclT m_decl)
    {
        return null;
    }

    /**
      Add a class member to a struct.
     */
    void actOnInterfaceBaseClass(DeclT if_decl, ref Id name)
    {
        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, Attribute att)
    {
        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 actOnForStmt(ref Token forTok, StmtT init, ExprT cond, ExprT incre, StmtT forBody)
    {
        return null;
    }

    /**
     */
    StmtT actOnDeclStmt(DeclT decl)
    {
        return null;
    }

    StmtT actOnStartOfSwitchStmt(Token _switch, ExprT exp)
    {
        return null;
    }

    void actOnCaseStmt(StmtT stmt, Token _case, ExprT[] exps, StmtT[] stmts)
    {
    }

    void actOnDefaultStmt(StmtT stmt, Token _default, StmtT[] stmts)
    {
    }

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

    /**
      This is called when strings are used in expression
     */
    ExprT actOnStringExp(Token t)
    {
        return null;
    }

    /**
      Unary operator.
     */
    ExprT actOnUnaryOp(Token op, ExprT operand)
    {
        return null;
    }

    /**
      Binary operator.
     */
    ExprT actOnBinaryOp(SLoc op_loc, 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, SourceLocation 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;
    }

    /**
      Called when function calls are encountered.
     */
    ExprT actOnIndexExpr(ExprT array, ref Token left_bracket, ExprT index,
                        ref Token right_bracket)
    {
        return null;
    }

    /**
      Cast expression.
     */
    ExprT actOnCastExpr(ref Token _cast, Id type, ExprT exp)
    {
        return null;
    }

    /**
      New expression.
     */
    ExprT actOnNewExpr(ref Id type, ExprT[] a_args, ExprT[] c_args)
    {
        return null;
    }

    /**
      Array Literal expression.
     */
    ExprT actOnArrayLiteralExpr(ExprT[] exps, SLoc start, SLoc end)
    {
        return null;
    }

    /**
      Null expression.
     */
    ExprT actOnNullExpr(SLoc pos)
    {
        return null;
    }
}

/**
  Doesn't do anything at all - can be used for benchmarking the parser.
 */
class NullAction : Action
{
}