【自制编程语言】1 - 基本语句(1)

前言

已经是年底了,本篇文章应该也是今年的最后一篇了。于是,突发奇想,想要来自制一个编程语言。也算是锻炼自己的代码能力吧。

冰冻三尺,非一日之寒。

同样,制作任何的东西,都是这样,罗马不是一天建成的,一个好的编程语言也不是一天建成的。我们能做的,就是先从基础开始,一点一点往上加入内容。一开始的东西可能非常简陋,甚至不能叫做是编程语言。但最终,随着新功能的加入,我们会发现,做出来的东西越来越像样了。

在阅读文章的时候,建议大家也动手写写。不需要完全一样,想要加入一些新的东西或者其他的修改也可以,尽可以根据自己的喜好修改。

实现功能

本期的功能实现,非常简单。
首先是编译方式的处理。我们使用朴素的命令行参数的形式,我们的编译的程序名(编译器的名字)是main,那么编译方式如下:

main test.txt

表示运行test.txt。

指令的处理,我们目前先写两个指令,练练手。分别是:SET和PRINT
SET

SET A 10

表示定义一个变量,值为10.

PRINT
输出变量的值。

命令行参数

现在我们是需要通过命令行的参数来获取要编译的文件名的。获取的方法,可以使用命令行参数的形式,这是C++语言的自带功能(不需要依赖操作系统的库)。

int main(int argc,char** argv);

通过这样的定义,我们就能获取命令行参数了。
我们做个试验,看看这些命令行参数是如何在argc和argv中排放的。

#include<iostream>
using namespace std;
int main(int argc,char** argv){
	for(int i=0;i<argc;i++){
		cout<<i<<" "<<argv[i]<<endl;
	}
}

运行时,随意输入一些参数进去。

因此,我们发现:从argv[1]开始往后,都是命令行参数,顺次存放在argv[1],argv[2]...中。

语法实现

关于变量的值的存放,我们考虑使用结构体。
其中,VARI_CTL控制多个变量的存放。(其实这里的vari数组应该使用malloc分配动态数组,否则变量最多只能有255个,这里偷了个懒)然后封装类函数,查询变量的值。
从文件读入,可以使用fscanf。我们这里使用循环的方式反复读入语句,由于每个语句使用空格分割,使用fscanf读入字符串即可。
(如果PRINT语句的语法修改为PRINT(A)的话,实现方法会更加复杂,因为要判断括号)
代码添加了注释,读起来应该比较容易理解。

完整的代码:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
struct VARIABLE{
        string name;    //变量名 
        int val;                //变量的值 
};
struct VARI_CTL{
        VARIABLE vari[255];     //255个变量
        int count;                      //变量目前为止的个数 
        VARI_CTL(){
                count=0;
        } 
        void set(string name,int a){            //设置一个变量 
                vari[count].name=name;
                vari[count].val=a;
                count++;
        }
        VARIABLE &get_vari(string name){
                for(int i=0;i<count;i++){
                        if(vari[i].name==name)return vari[i];
                }
                cout<<"[Error]:Can\'t find variable name.";
                exit(0);
        }
        int get_val(string name){
                for(int i=0;i<count;i++){
                        if(vari[i].name==name)return vari[i].val;
                }
                cout<<"[Error]:Can\'t find variable name.";
                exit(0);
        }
}vari_ctl;
int main(int argc,char** argv){
        string s;               //每次从文件读入的字串 
        char sc[100];   //为了使用fscanf,需要使用C风格字符串 
        FILE *fp=fopen(argv[1],"r");
        if(fp==NULL){   //找不到文件 
                printf("[Error]:Can\'t find input file \"%s\" .",argv[1]);
                exit(0);
        }
        for(;;){
                fscanf(fp,"%s",sc);
                s=sc;           //使用string类型更加方便使用
                if(s=="EXIT"){
                        system("pause");
                        exit(0);
                } 
                else if(s=="SET"){
                        char t[100],u[100];             //格式:SET 变量名 数字 
                        fscanf(fp,"%s %s",t,u);
                        int a;
                        sscanf(u,"%d",&a);              //字符串转数字 
                        vari_ctl.set(t,a);              //设置数值 
                }
                else if(s=="PRINT"){
                        char t[100];
                        fscanf(fp,"%s",t);
                        if(t[0]=='\"'){                 //字符串的输出 
                                for(int i=1;i<strlen(t)-1;i++){
                                        printf("%c",t[i]);
                                }
                        }
                        else{
                                cout<<vari_ctl.get_val(t);
                        }
                }
                else{
                        cout<<"[Error]:Illegal command.";
                        exit(0);
                }
        }
}
posted @ 2021-12-31 18:40  计算机知识杂谈  阅读(775)  评论(1编辑  收藏  举报