SharpC-A-C-Interpreter-In-C-0000

24次阅读

共计 12870 个字符,预计需要花费 33 分钟才能阅读完成。

Update:

  • igame@May/16/2019:

    • Removed “ExternalFunction”: it’s redundent. So did the “RegesterExternalFunction”.
    • Renamed “InternalFunctions” directory(or namespace) to “ExtraFunctions”.
    • Removed Flex/Bison project which based on WinSDK 8.1.
    • Renamed extra function “input” to “inputDlg”.
    • Fixed bug: “inputDlg” won’t work.

在维护新建对象 (my son) 的时候,利用对象休眠的闲暇,写了个习作。

咸盐少许。

通常,编译原理或编译技术都会建议使用 yacc 或 lex 来实现语言、公式的解释器或编译器。鉴于实现一个语言编译器或解释器的困难,大多数猿类都会使用这类工具。不过,本文穿越到了工具出现以前的时代,同时又开启了金手指:带了 c#、Flex 和 Bison。既是习作,故使用 c# 手工打造了一个简单的 c 语言解释器,而并未使用 Flex 和 Bison。
这个解释器被胡乱命名为 SharpC。它实现了 c 语言的如下部分特性:

特性 支持程度 说明
基本的类型 char, short, int, float, struct 对于 unsigned, signed 的区分不明显,不支持 const 关键字 now keyword “const” is supported。
函数 支持 包括不定参数函数,支持递归,支持嵌套定义。
表达式 仅不支持?:三元操作符 逗号操作符未测试。
指针 支持 这意味着支持内存操作,也意味支持字符串。
控制结构 仅不支持 goto 包括:if/else, for, while, do/while, switch/case/default/break, return, continue.
内建函数 malloc(), free(), print(), vararg(), varlen(), input(), InputDlg(), prompt(), confirm() According updating of May-16-19, it’s easier to add new functions into system.
其它 所有其它 c 语言功能皆不支持 诸如: #符号,macro, typedef 等。

我们先看看最终结果,对于这样的一个 c 语言测试代码:

/*
* This is a multi-line comment.
*
*/
// This is a single line comment.

char globalChar = 'A';
short globalShort = 333;
int globalInt = 1;    // Global scope declaration
float globalFloat = 1.2345;

char* ptr = "abcdefg" "hijklmn";

void funcFwdDecl();    // forwarding declaration

void funcWithoutArg()
{
    // Variable declaration and initialization
    int x = 1;

    // Empty statement
    ;

    { // anonymous block
        int y = 3;
    } // end of block

    // Test bare expression
    1 < 2;
    1 <= 2;
    2 > 1;
    2 >= 1;
    // Test comments
    x += 1 // This is a comment
    ;

    // Test assign
    x = 10 - 3;
    x += 1;
    x -= 1;
    x *= 1;
    x /= 1;
    x %= 1;
    x &= 1;
    x |= 1;
    x ^= 1;
    x <<= 1;
    x >>= 1;

    // Test pre/post operator
    x = x++;
    x = x--;
    x = ++x;
    x = --x;

    // Control flow
    // If with statement
    if (x <= 1)
        x++;

    // If/else
    if (x <= 2)
        x--;
    else
        x++;

    // if/else matching 1
    if (x <= 3)
        --x;
    else
        if (x <= 4)
            x++;

    if (x <= 5)
        x += 1;
    else
        if (x <= 6)
            x += 2;
        else
            x += 3;

    // If with block
    if (x <= 7)
    {x /= 10;}
    else
    {x *= 10;}

    if (1 < 2)
        x = 0;
    else
        if (3 < 4)
          x = 1;
        else
           x = 2; 
    
    // for loop
    // Commonly for loop with single statemnt
    for(int i = 0; i < 100; i++)
        x++;

    // for loop with block
    for(int i = 0; i < 100; i++)
    {
        x++;
        x--;
    }

    // for loop with long initializer
    int i = 0;
    for(i = 1, x = 0; i < 100; i++)
    {
        x--;
        x++;
    }

    // for loop with long iterator
    for(int l = 0; l < 100; l++, x--, x++, x--)
        x--;

    // for loop with break & continue
    for(int l = 0; l < 100; l++)
    {if (l > 100)
            break;
        else
            if (l > 50)
                continue;
    }

    // while with single statement
    while(1 < 2) x++;

    // while with block
    while(x < 3)
    {
        x++;
        x;
    }

    // while with break & continue
    while(x < 10)
    {if (x > 5)
            break;
        else
            continue;

        x++;
    }

    // do/while
    do{
        x++;
        x--;
        --x;
        ++x;
    }// comments
    while(1);

    switch(x)
    {
        case '0': break;
        case 'a': break;
        case '\t': break;
        case 1:
        case 2:
        case 3: break;
        case 5:
            {
                x--;
                x++;
                x *= 10;
            }
            break;
        case 6:
            switch(x)
            {
                case 1:
                case 2:
                case 3: break;
                case 4:
                    { }
                    break;
                default: break;
            }
            break;
        default: x++; break;
    }


    return 1; // This will cause an error.
} // end of func

void funcWithArg(int var1)
{return;}

void funcWithManyArg(int var1, int var2, int var3)
{
    do{
        var1++;
        var2--;

        if (var1 + var2 <= var3)
            return ;
    }while(1 > 2);

    while(var2 > var1)
    {
        int ddd = 100;

        continue;
    }

    int innerFunc(int var4, int var5)
    {var4 = var1 + var2 + var3 / var5;}

    
    innerFunc(1, 2);
}

int funcInt()
{return ; // This will cause an error.}

int funcVar(...)
{funcVar(1, 2, 3);
    return 0;
}

SharpC 的分析结果如下:

SharpC.Grammar.Variable:    Line: 7 Pos: 7 "globalChar"
SharpC.Grammar.Statement:    Line: 7 Pos: 7 "globalChar ='A'"SharpC.Grammar.Variable:    Line: 8 Pos: 8"globalShort"SharpC.Grammar.Statement:    Line: 8 Pos: 8"globalShort = 333"SharpC.Grammar.Variable:    Line: 9 Pos: 6"globalInt"SharpC.Grammar.Statement:    Line: 9 Pos: 6"globalInt = 1"SharpC.Grammar.Variable:    Line: 10 Pos: 8"globalFloat"SharpC.Grammar.Statement:    Line: 10 Pos: 8"globalFloat = 1.2345"SharpC.Grammar.Variable:    Line: 12 Pos: 8"ptr"SharpC.Grammar.Statement:    Line: 12 Pos: 8"ptr = "abcdefg" "hijklmn""
SharpC.Grammar.Variable:    Line: 19 Pos: 7 "x"
SharpC.Grammar.Statement:    Line: 19 Pos: 7 "x = 1"
SharpC.Grammar.Statement:    Line: 22 Pos: 3 ";"
SharpC.Grammar.Variable:    Line: 25 Pos: 7 " "
SharpC.Grammar.Statement:    Line: 25 Pos: 7 "y ="
SharpC.Grammar.Statement:    Line: 29 Pos: 3 "1 < 2;"
SharpC.Grammar.Statement:    Line: 30 Pos: 3 "1 <= 2;"
SharpC.Grammar.Statement:    Line: 31 Pos: 3 "2 > 1;"
SharpC.Grammar.Statement:    Line: 32 Pos: 3 "2 >= 1;"
SharpC.Grammar.Statement:    Line: 34 Pos: 3 "x += 1 // This is a comment
    ;"SharpC.Grammar.Statement:    Line: 38 Pos: 3"x = 10 - 3;"SharpC.Grammar.Statement:    Line: 39 Pos: 3"x += 1;"SharpC.Grammar.Statement:    Line: 40 Pos: 3"x -= 1;"SharpC.Grammar.Statement:    Line: 41 Pos: 3"x *= 1;"SharpC.Grammar.Statement:    Line: 42 Pos: 3"x /= 1;"SharpC.Grammar.Statement:    Line: 43 Pos: 3"x %= 1;"SharpC.Grammar.Statement:    Line: 44 Pos: 3"x &= 1;"SharpC.Grammar.Statement:    Line: 45 Pos: 3"x |= 1;"SharpC.Grammar.Statement:    Line: 46 Pos: 3"x ^= 1;"SharpC.Grammar.Statement:    Line: 47 Pos: 3"x <<= 1;"SharpC.Grammar.Statement:    Line: 48 Pos: 3"x >>= 1;"SharpC.Grammar.Statement:    Line: 51 Pos: 3"x = x++;"SharpC.Grammar.Statement:    Line: 52 Pos: 3"x = x--;"SharpC.Grammar.Statement:    Line: 53 Pos: 3"x = ++x;"SharpC.Grammar.Statement:    Line: 54 Pos: 3"x = --x;"SharpC.Grammar.Statement:    Line: 59 Pos: 4"x++;"SharpC.Grammar.ControlFlow.IfThen:    Line: 58 Pos: 3"if (x <= 1)
        "SharpC.Grammar.Statement:    Line: 63 Pos: 4"x--;"SharpC.Grammar.ControlFlow.IfThen:    Line: 62 Pos: 3"if (x <= 2)
        "SharpC.Grammar.Statement:    Line: 65 Pos: 4"x++;"SharpC.Grammar.ControlFlow.IfThen:    Line: 62 Pos: 3"if (x <= 2)
        x--;
    else
        "SharpC.Grammar.Statement:    Line: 69 Pos: 4"--x;"SharpC.Grammar.ControlFlow.IfThen:    Line: 68 Pos: 3"if (x <= 3)
        "SharpC.Grammar.Statement:    Line: 72 Pos: 5"x++;"SharpC.Grammar.ControlFlow.IfThen:    Line: 71 Pos: 4"if (x <= 4)
            "SharpC.Grammar.ControlFlow.IfThen:    Line: 68 Pos: 3"if (x <= 3)
        --x;
    else
        "SharpC.Grammar.Statement:    Line: 75 Pos: 4"x += 1;"SharpC.Grammar.ControlFlow.IfThen:    Line: 74 Pos: 3"if (x <= 5)
        "SharpC.Grammar.Statement:    Line: 78 Pos: 5"x += 2;"SharpC.Grammar.ControlFlow.IfThen:    Line: 77 Pos: 4"if (x <= 6)
            "SharpC.Grammar.ControlFlow.IfThen:    Line: 74 Pos: 3"if (x <= 5)
        x += 1;
    else
        "SharpC.Grammar.Statement:    Line: 80 Pos: 5"x += 3;"SharpC.Grammar.ControlFlow.IfThen:    Line: 74 Pos: 3"if (x <= 5)
        x += 1;
    else
        if (x <= 6)
            x += 2;
        else
            "SharpC.Grammar.Statement:    Line: 85 Pos: 4"x /= 10;"SharpC.Grammar.ControlFlow.IfThen:    Line: 83 Pos: 3"if (x <= 7)
    {x /= 10;}"SharpC.Grammar.Statement:    Line: 89 Pos: 4"x *= 10;"SharpC.Grammar.ControlFlow.IfThen:    Line: 83 Pos: 3"if (x <= 7)
    {x /= 10;}
    else
    {x *= 10;}"SharpC.Grammar.Statement:    Line: 93 Pos: 4"x = 0;"SharpC.Grammar.ControlFlow.IfThen:    Line: 92 Pos: 3"if (1 < 2)
        "SharpC.Grammar.Statement:    Line: 96 Pos: 6"x = 1;"SharpC.Grammar.ControlFlow.IfThen:    Line: 95 Pos: 4"if (3 < 4)
          "SharpC.Grammar.ControlFlow.IfThen:    Line: 92 Pos: 3"if (1 < 2)
        x = 0;
    else
        "SharpC.Grammar.Statement:    Line: 98 Pos: 7"x = 2;"SharpC.Grammar.ControlFlow.IfThen:    Line: 92 Pos: 3"if (1 < 2)
        x = 0;
    else
        if (3 < 4)
          x = 1;
        else
           "SharpC.Grammar.Variable:    Line: 102 Pos: 11"i"SharpC.Grammar.Statement:    Line: 102 Pos: 11"i = 0"SharpC.Grammar.Statement:    Line: 103 Pos: 4"x++;"SharpC.Grammar.ControlFlow.ForLoop:    Line: 102 Pos: 3"for(int i = 0; i < 100; i++)
        "SharpC.Grammar.Variable:    Line: 106 Pos: 11"i"SharpC.Grammar.Statement:    Line: 106 Pos: 11"i = 0"SharpC.Grammar.Statement:    Line: 108 Pos: 4"x++;"SharpC.Grammar.Statement:    Line: 109 Pos: 4"x--;"SharpC.Grammar.ControlFlow.ForLoop:    Line: 106 Pos: 3"for(int i = 0; i < 100; i++)
    {"SharpC.Grammar.Variable:    Line: 113 Pos: 7"i"SharpC.Grammar.Statement:    Line: 113 Pos: 7"i = 0"SharpC.Grammar.Statement:    Line: 114 Pos: 7"i = 1, x = 0;"SharpC.Grammar.Statement:    Line: 116 Pos: 4"x--;"SharpC.Grammar.Statement:    Line: 117 Pos: 4"x++;"SharpC.Grammar.ControlFlow.ForLoop:    Line: 114 Pos: 3"for(i = 1, x = 0; i < 100; i++)
    {"SharpC.Grammar.Variable:    Line: 121 Pos: 11"l"SharpC.Grammar.Statement:    Line: 121 Pos: 11"l = 0"SharpC.Grammar.Statement:    Line: 122 Pos: 4"x--;"SharpC.Grammar.ControlFlow.ForLoop:    Line: 121 Pos: 3"for(int l = 0; l < 100; l++, x--, x++, x--)
        "SharpC.Grammar.Variable:    Line: 125 Pos: 11"l"SharpC.Grammar.Statement:    Line: 125 Pos: 11"l = 0"SharpC.Grammar.ControlFlow.Break:    Line: 128 Pos: 5"break;"SharpC.Grammar.ControlFlow.IfThen:    Line: 127 Pos: 4"if (l > 100)
            "SharpC.Grammar.ControlFlow.Continue:    Line: 131 Pos: 6"continue"SharpC.Grammar.ControlFlow.IfThen:    Line: 130 Pos: 5"if (l > 50)
                "SharpC.Grammar.ControlFlow.IfThen:    Line: 127 Pos: 4"if (l > 100)
            break;
        else
            "SharpC.Grammar.ControlFlow.ForLoop:    Line: 125 Pos: 3"for(int l = 0; l < 100; l++)
    {"SharpC.Grammar.Statement:    Line: 135 Pos: 16"x++;"SharpC.Grammar.ControlFlow.WhileLoop:    Line: 135 Pos: 3"while(1 < 2) "SharpC.Grammar.ControlFlow.WhileLoop:    Line: 135 Pos: 3"while(1 < 2) "SharpC.Grammar.Statement:    Line: 140 Pos: 4"x++;"SharpC.Grammar.Statement:    Line: 141 Pos: 4"x;"SharpC.Grammar.ControlFlow.WhileLoop:    Line: 138 Pos: 3"while(x < 3)
    {"SharpC.Grammar.ControlFlow.WhileLoop:    Line: 138 Pos: 3"while(x < 3)
    {"SharpC.Grammar.ControlFlow.Break:    Line: 148 Pos: 5"break;"SharpC.Grammar.ControlFlow.IfThen:    Line: 147 Pos: 4"if (x > 5)
            "SharpC.Grammar.ControlFlow.Continue:    Line: 150 Pos: 5"continue"SharpC.Grammar.ControlFlow.IfThen:    Line: 147 Pos: 4"if (x > 5)
            break;
        else
            "SharpC.Grammar.Statement:    Line: 152 Pos: 4"x++;"SharpC.Grammar.ControlFlow.WhileLoop:    Line: 145 Pos: 3"while(x < 10)
    {"SharpC.Grammar.ControlFlow.WhileLoop:    Line: 145 Pos: 3"while( x < 10)
    {"SharpC.Grammar.Statement:    Line: 157 Pos: 4"x++;"SharpC.Grammar.Statement:    Line: 158 Pos: 4"x--;"SharpC.Grammar.Statement:    Line: 159 Pos: 4"--x;"SharpC.Grammar.Statement:    Line: 160 Pos: 4"++x;"SharpC.Grammar.ControlFlow.DoWhileLoop:    Line: 156 Pos: 3"do{"SharpC.Grammar.ControlFlow.Case:    Line: 166 Pos: 4"case '0':"SharpC.Grammar.ControlFlow.Break:    Line: 166 Pos: 14"break;"SharpC.Grammar.ControlFlow.Case:    Line: 167 Pos: 4"case 'a':"SharpC.Grammar.ControlFlow.Break:    Line: 167 Pos: 14"break;"SharpC.Grammar.ControlFlow.Case:    Line: 168 Pos: 4"case '\t':"SharpC.Grammar.ControlFlow.Break:    Line: 168 Pos: 15"break;"SharpC.Grammar.ControlFlow.Case:    Line: 169 Pos: 4"case 1:"SharpC.Grammar.ControlFlow.Case:    Line: 170 Pos: 4"case 2:"SharpC.Grammar.ControlFlow.Case:    Line: 171 Pos: 4"case 3:"SharpC.Grammar.ControlFlow.Break:    Line: 171 Pos: 12"break;"SharpC.Grammar.ControlFlow.Case:    Line: 172 Pos: 4"case 5:"SharpC.Grammar.Statement:    Line: 174 Pos: 5"    x--"SharpC.Grammar.Statement:    Line: 175 Pos: 5"    x++"SharpC.Grammar.Statement:    Line: 176 Pos: 5"    x *= 10"SharpC.Grammar.ControlFlow.Break:    Line: 178 Pos: 5"break;"SharpC.Grammar.ControlFlow.Case:    Line: 179 Pos: 4"case 6:"SharpC.Grammar.ControlFlow.Case:    Line: 182 Pos: 6"case 1:"SharpC.Grammar.ControlFlow.Case:    Line: 183 Pos: 6"case 2:"SharpC.Grammar.ControlFlow.Case:    Line: 184 Pos: 6"case 3:"SharpC.Grammar.ControlFlow.Break:    Line: 184 Pos: 14"break;"SharpC.Grammar.ControlFlow.Case:    Line: 185 Pos: 6"case 4:"SharpC.Grammar.ControlFlow.Break:    Line: 188 Pos: 7"break;"SharpC.Grammar.ControlFlow.Break:    Line: 189 Pos: 15"break;"SharpC.Grammar.ControlFlow.Switch:    Line: 180 Pos: 5"switch(x)
            {
                case 1:
                case 2:
                case 3: break;
                case 4:
                    { }
                    break;
                default: break;
            }"SharpC.Grammar.ControlFlow.Break:    Line: 191 Pos: 5"break;"SharpC.Grammar.Statement:    Line: 192 Pos: 13"x++;"SharpC.Grammar.ControlFlow.Break:    Line: 192 Pos: 18"break;"SharpC.Grammar.ControlFlow.Switch:    Line: 164 Pos: 3"switch(x)
    {
        case '0': break;
        case 'a': break;
        case '\t': break;
        case 1:
        case 2:
        case 3: break;
        case 5:
            {
                x--;
                x++;
                x *= 10;
            }
            break;
        case 6:
            switch(x)
            {
                case 1:
                case 2:
                case 3: break;
                case 4:
                    { }
                    break;
                default: break;
            }
            break;
        default: x++; break;
    }"1>>Syntax error: Line: 196 Pos: 3"return 1;": return value type does not match the function type.
SharpC.Grammar.ControlFlow.Return:    Line: 196 Pos: 3 "return 1;"
SharpC.Grammar.ControlFlow.Return:    Line: 201 Pos: 3 "return;"
SharpC.Grammar.Statement:    Line: 207 Pos: 4 "var1++;"
SharpC.Grammar.Statement:    Line: 208 Pos: 4 "var2--;"
SharpC.Grammar.ControlFlow.Return:    Line: 211 Pos: 5 "return ;"
SharpC.Grammar.ControlFlow.IfThen:    Line: 210 Pos: 4 "if (var1 + var2 <= var3)"
SharpC.Grammar.ControlFlow.DoWhileLoop:    Line: 206 Pos: 3 "do{"
2>>Syntax error: Line: 214 Pos: 3 "while": ';' is expected.
SharpC.Grammar.ControlFlow.DoWhileLoop:    Line: 206 Pos: 3 "do{
        var1++;
        var2--;

        if (var1 + var2 <= var3)
            return ;
    }while(1 > 2)"SharpC.Grammar.Statement:    Line: 223 Pos: 4"var4 = var1 + var2 + var3 / var5;"SharpC.Grammar.Statement:    Line: 227 Pos: 3"innerFunc(1, 2);"3>>Syntax error: Line: 232 Pos: 3"return ;": return value type does not match the function type.
SharpC.Grammar.ControlFlow.Return:    Line: 232 Pos: 3 "return ;"
SharpC.Grammar.Statement:    Line: 237 Pos: 3 "funcVar(1, 2, 3);"
SharpC.Grammar.ControlFlow.Return:    Line: 238 Pos: 3 "return 0;"
Time consumption: 0.5753843 sec

打印分析生成的语法树以还原代码:

char * $var_char_ptr_6$ 
(const) refers to $var_char_ptr_6$ Data length:15
void * malloc(int size)
void free(void * ptr)
int input(char * title, char * message, char * defValue, char * format, char * errMsg, char * result)
int confirm(char * title, char * msg)
void prompt(char * title, char * msg)
void print(...)
char vararg(int argIdx)
int varlen()
char globalChar 
globalChar = 65
short globalShort 
globalShort = 333
int globalInt 
globalInt = 1
float globalFloat 
globalFloat = 1.2345
char * ptr 
ptr = $var_char_ptr_6$
void funcFwdDecl()
void funcWithoutArg()
{
    int x 
    x = 1
    
    {
        int y 
        y = 3
    }
    1 < 2
    1 <= 2
    2 > 1
    2 >= 1
    x += 1
    x = 10 - 3
    x += 1
    x += 1
    x *= 1
    x /= 1
    x %= 1
    x &= 1
    x |= 1
    x ^= 1
    x <<= 1
    x >>= 1
    x = x++
    x = x--
    x = ++x
    x = --x
    if(x <= 1)
        {x++}
    if(x <= 2)
        {x--}
    else
        {x++}
    if(x <= 3)
        {--x}
    else
        {if(x <= 4)
                {x++}
        }
    if(x <= 5)
        {x += 1}
    else
        {x += 3}
    if(x <= 7)
        {x /= 10}
    else
        {x *= 10}
    if(1 < 2)
        {x = 0}
    else
        {x = 2}
    for(
    Initalizer: 
        int i 
        i = 0
    Condition: i < 100
    Iterator: i++
    {x++}
    for(
    Initalizer: 
        int i 
        i = 0
    Condition: i < 100
    Iterator: i++
    {
        x++
        x--
    }
    int i 
    i = 0
    for(
    Initalizer: 
        i = 1
    Condition: i < 100
    Iterator: i++
    {
        x--
        x++
    }
    for(
    Initalizer: 
        int l 
        l = 0
    Condition: l < 100
    Iterator: l++
    {x--}
    for(
    Initalizer: 
        int l 
        l = 0
    Condition: l < 100
    Iterator: l++
    {if(l > 100)
            {break;}
        else
            {if(l > 50)
                    {continue;}
            }
    }
    while(1 < 2)
    {x++}
    while(x < 3)
    {
        x++
        x
    }
    while(x < 10)
    {if(x > 5)
            {break;}
        else
            {continue;}
        x++
    }
    do
    {
        x++
        x--
        --x
        ++x
    }
    while(1)
    switch(x)
    {
        default:
            {
                x++
                break;
            }
        case 48:
            {break;}
        case 97:
            {break;}
        case 9:
            {break;}
        case 1:
            { }
        case 2:
            { }
        case 3:
            {break;}
        case 5:
            {
                {
                    x--
                    x++
                    x *= 10
                }
                break;
            }
        case 6:
            {switch(x)
                {
                    default:
                        {break;}
                    case 1:
                        { }
                    case 2:
                        { }
                    case 3:
                        {break;}
                    case 4:
                        {{}
                            break;
                        }
                }
                break;
            }
    }
    return 1
}
void funcWithArg(int var1)
{return ;}
void funcWithManyArg(int var1, int var2, int var3)
{
    do
    {
        var1++
        var2--
        if(var1 + var2 <= var3)
            {return ;}
    }
    while(1 > 2)
    int innerFunc(int var4, int var5)
    {var4 = var1 + var2 + var3 / var5}
    innerFunc(1,2,)
}
int funcInt()
{return ;}
int funcVar(...)
{funcVar(1,2,3,)
    return 0
}

可以看到,结果大致与源代码相同。

正文完
 0