先记在这里,有时间再来仔细整理:

词法分析:
关键字定义:

/* This enum contains all the keywords and operators
 * used in the language.
 */
enum
{
    /* Keywords */
    KW_BREAK            = 1000, /* "break" keyword */
    KW_CASE,                    /* "case" keyword */
    KW_CONTINUE,                /* "continue" keyword */
    KW_DEFAULT,                 /* "default" keyword */
    KW_DO,                      /* "do" keyword */
    KW_ELSE,                    /* "else" keyword */
    KW_EXTERN,                  /* "extern" keyword */
    KW_GOTO,                    /* "goto" keyword */
    KW_IF,                      /* "if" keyword */
    KW_LABEL,                   /* "label" keyword */
    KW_MODULE,                  /* "module" keyword */
    KW_RETURN,                  /* "return"keyword */
    KW_START,                   /* "start" keyword */
    KW_SWITCH,                  /* "switch" keyword */
    KW_WHILE,                   /* "while" keyword */

    /* Type identifiers */
    KW_BOOL,                    /* "bool" identifier */
    KW_CHAR,                    /* "char" identifier */
    KW_FLOAT,                   /* "float" identifier */
    KW_INT,                     /* "int" identifier */
    KW_UNTYPED,                 /* "untyped" identifier */
    KW_VOID,                    /* "void" identifier */

    /* Variable lexer tokens */
    LIT_BOOL,                   /* bool constant */
    LIT_CHAR,                   /* character constant */
    LIT_FLOAT,                  /* floating point constant */
    LIT_INT,                    /* integer constant */
    LIT_STRING,                 /* string constant */
    IDENTIFIER,                 /* identifier */

    /* Operators */
    OP_ADD,                     /* "+"  */
    OP_ASSIGN,                  /* "="  */
    OP_BITWISE_AND,             /* "&" */
    OP_BITWISE_COMPLEMENT,      /* "~"  */
    OP_BITWISE_LSHIFT,          /* "<<" */
    OP_BITWISE_OR,              /* "|" */
    OP_BITWISE_RSHIFT,          /* ">>" */
    OP_BITWISE_XOR,             /* "^"  */
    OP_DIVIDE,                  /* "/"  */
    OP_EQUAL,                   /* "==" */
    OP_GREATER,                 /* ">"  */
    OP_GREATEREQUAL,            /* ">=" */
    OP_LESS,                    /* "<"  */
    OP_LESSEQUAL,               /* "<=" */
    OP_LOGICAL_AND,             /* "&&" */
    OP_LOGICAL_OR,              /* "||" */
    OP_MODULUS,                 /* "%"  */
    OP_MULTIPLY,                /* "*"  */
    OP_NOT,                     /* "!"  */
    OP_NOTEQUAL,                /* "!=" */
    OP_SUBTRACT,                /* "-"  */
    OP_TERNARY_IF,              /* "?"  */
  
    /* Delimiters */
    ARROW,                      /* "->" */
    LBRACE,                     /* "{"  */
    RBRACE,                     /* "}"  */
    LBRACKET,                   /* "["  */
    RBRACKET,                   /* "]"  */
    COLON,                      /* ":"  */
    COMMA,                      /* ","  */
    LPAREN,                     /* "("  */
    RPAREN,                     /* ")"  */
    SEMICOLON                   /* ";"  */
}
tokens;

 

 

 

 


处理inger中的各种数据类型和标识符,如BOOL, unsigned long, float, char*,标识符等
typedef union
{
    unsigned long  uintvalue;
    BOOL    boolvalue;
    char   *stringvalue;
    char    charvalue;
    float   floatvalue;
    char   *identifier;
} Tokenvalue;


树节点结构(注意:树节点和抽象语法树节点是不同的):
typedef struct TreeNode
{
    void            *data;
    int              screenX;
    struct TreeNode *parent;
    List            *children; //一系列孩子
} TreeNode;

抽象语法树节点结构:
typedef struct AstNode
{
    int         id;  //表示节点的类型,如while节点,module节点
    Tokenvalue  val;
    Type       *type;
    int         lineno;
} AstNode;

抽象语法树的AstNode作为TreeNode的data成员保存,参考如下函数:
//参数id表示节点名,如:NODE_MODULE,NODE_GLOBAL等见nodenames.h
TreeNode *CreateAstNode( int id, int lineno )
{
    TreeNode *treeNode;
    AstNode *astNode;

    astNode = (AstNode *) MallocEx( sizeof( AstNode ) );
    astNode->id = id;
    astNode->lineno = lineno;
    astNode->val.uintvalue = 0;
    astNode->type = NULL;
    treeNode = CreateTreeNode( astNode );

    return( treeNode );
}
或者:
TreeNode *CreateAstNodeVal( int id, Tokenvalue val, int lineno )
{
    TreeNode *treeNode;
    AstNode *astNode;

    astNode = (AstNode *) MallocEx( sizeof( AstNode ) );
    astNode->id = id;
    astNode->lineno = lineno;
    astNode->val = val;
    astNode->type = NULL;
    treeNode = CreateTreeNode( astNode );

    return( treeNode );
}


//抽象语法树节点名
enum NodeNames
{
    NODE_MODULE = 0,
    NODE_START,
    NODE_EXTERN,
    NODE_GLOBAL,
    NODE_FUNCTION,
    NODE_FUNCTIONHEADER,
    NODE_MODIFIERS,
    NODE_PARAMLIST,
    NODE_PARAMBLOCK,
    NODE_PARAM,
    NODE_RETURNTYPE,
    NODE_DIMENSION,
    NODE_DIMENSIONBLOCK,
    NODE_BLOCK,
    NODE_STATEMENT,
    NODE_SWITCH,
    NODE_CASES,
    NODE_CASE,
    NODE_WHILE,
    NODE_GOTO,
    NODE_LABEL,
    NODE_IF,
    NODE_IDENT,
    NODE_RETURN,
    NODE_CONTINUE,
    NODE_BREAK,
    NODE_DECLBLOCK,
    NODE_DECLARATION,
    NODE_INITIALIZER,
    NODE_INDEXBLOCK,
    NODE_REFERENCE,
    NODE_INDEX,
    NODE_EXPRESSION,
    NODE_LOGICAL_OR,
    NODE_LOGICAL_AND,
    NODE_BITWISE_OR,
    NODE_BITWISE_XOR,
    NODE_BITWISE_AND,
    NODE_EQUAL,
    NODE_NOTEQUAL,
    NODE_GREATER,
    NODE_GREATEREQUAL,
    NODE_LESS,
    NODE_LESSEQUAL,
    NODE_BITWISE_LSHIFT,
    NODE_BITWISE_RSHIFT,
    NODE_ASSIGN,
    NODE_BINARY_ADD,
    NODE_BINARY_SUBTRACT,
    NODE_UNARY_ADD,
    NODE_UNARY_SUBTRACT,
    NODE_MULTIPLY,
    NODE_DIVIDE,
    NODE_MODULUS,
    NODE_BITWISE_COMPLEMENT,
    NODE_ADDRESS,
    NODE_DEREFERENCE,
    NODE_NOT,
    NODE_APPLICATION,
    NODE_INDEXER,
    NODE_ARGUMENTS,
    NODE_FACTOR,

    NODE_BOOL,
    NODE_CHAR,
    NODE_FLOAT,
    NODE_INT,
    NODE_UNTYPED,
    NODE_VOID,

    NODE_LIT_BOOL,
    NODE_LIT_CHAR,
    NODE_LIT_FLOAT,
    NODE_LIT_INT,
    NODE_LIT_STRING,
    NODE_LIT_IDENTIFIER,

    NODE_INT_TO_FLOAT,
    NODE_CHAR_TO_INT,
    NODE_CHAR_TO_FLOAT,

    NODE_UNKNOWN = -1
};


输出抽象语法树:
/*
 * PRINTING ROUTINES
 */
void PrintAst( TreeNode *source )
{
    PrintTree( source, GetAstNodeData, 4 );
}
PrintTree的实现如下,这里传递的参数levels等于4
void PrintTree( TreeNode *source, DataFunction dataFunction, int levels )
{
    int printDepth = 0;
    BOOL loop;
    char *str;
    int i;

    /* TODO: We're going to have to make a new macro.
     * Don't use DEBUG for this.
     */
    DEBUG( "Called\n" );

    /* If tree is empty, abort. */
    if( source == NULL )
    {
        return;
    }

    /* Walk through tree to determine x-offsets for
     * each node.
     */
    LayoutTree( source, LEFT_OFFSET );

/* Print nodes. */
依次通过调用函数指针dataFunction所指向的函数(实际上是函数GetAstNodeData)
来输出每个节点的节点名,节点的token的值,类型名,以及行号,参考下面的GetAstNodeData函数

    for( i = 0; i < levels; i++ )
    {
        str = dataFunction( source, i );
        PrintChars( source->screenX - strlen( str ) / 2, ' ' );
        printf( "%s\n", str );
    }
    PrintChars( source->screenX, ' ' );
    printf( "%c", VERTBAR );

    printDepth = 0;
    do
    {
        currentX = 0;
        printf("\n");
        PrintNode( source, 0, printDepth, 0, dataFunction, 0 );
        currentX = 0;
        printf("\n");
        PrintNode( source, 0, printDepth, 1, dataFunction, 0 );
        currentX = 0;
        printf("\n");
        for( i = 0; i < levels; i++ )
        {
            PrintNode( source, 0, printDepth, 2, dataFunction, i );
            currentX = 0;
            printf("\n");
        }
        loop = PrintNode( source, 0, printDepth, 3, dataFunction, 0 );
        printDepth++;
    }
    while( loop );
}

添加一个孩子的操作只需要将新节点插入到孩子链表尾部即可
void AddTreeChild( TreeNode *parentnode, TreeNode *node )
{
    /* Do not act on an empty node. */
    if( node == NULL ) return;

    /* If the tree is empty, add the first root node. */
    if( parentnode == NULL )
    {
       node->parent = NULL;
    }
    else
    /* Tree is not empty. Add the new node to [parentnode]'s
     * children list. */
    {
       node->parent = parentnode;

       ListAppend( parentnode->children, node );
    }
}

而RemoveAstNode则删除整个子树
/* Remove node [node] from ast. The node contents
 * and its children get deleted.
 *
 * Pre:  [node] is not NULL.
 */
void RemoveAstNode( TreeNode *node );


inger编译流程:
1. 预处理,关键函数为Preprocess
2. 语法分析,构建抽象语法树,关键函数Parse,Parse也是构造抽象语法树的入口函数,如果语法分析没有发现错误则跳到第3步
3. 根据抽象语法树来建立符号表关键函数为CreateSymbolTable( ast );
4. 语义分析,关键函数:
a) CheckLeftValues( ast );
b) CheckArgCount( ast );
c) CheckSwitchStatements( ast );
d) CheckFunctionReturns( ast );

5.  根据抽象语法树生成代码,关键函数GenerateCode( ast );