cscの作法 その38 インタープリタ

#概要

cscの作法、調べてみた。
練習問題やってみた。

#練習問題

俺言語インタープリタを作れ。

#写真

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/72b14364-1bb9-dc4a-3560-d83a48435439.png)


#サンプルコード


```
using System;
using System.Windows.Forms;
using System.Drawing;

class form1: Form {
	TextBox bo1;
	byte[] ram = new byte[256];
	byte Rmd = 233; // random no address
	byte Bnd = 234; // line no saigo no address
	byte Pcc = 235; // program counter no address

	byte Lbf = 237; // buf no saisyo
	byte Ptr; 		// genzaino pointer
	byte Cur; 		// line pointer
	byte c;			// atai
	byte adr;		// ver no address
	byte adr2;		// ver2 no address
	byte val;		// var no atai
	form1() {
		Text = "oregengo";
		ClientSize = new Size(400, 600);
		bo1 = new TextBox();
		bo1.Location = new Point(50, 50);
		bo1.Width = 300;
		bo1.Height = 450;
		bo1.Multiline = true;
		bo1.Text = "10 a=1\r\n30 b=a/15\r\n40 #=%=0*120\r\n50 b=a/5\r\n60 #=%=0*140\r\n70 b=a/3\r\n80 #=%=0*160\r\n90 ?=a\r\n100 #=a<100*180\r\n110 #=300\r\n120 ?=\"fizzbuzz \"\r\n130 #=180\r\n140 ?=\"buzz \"\r\n150 #=180\r\n160 ?=\"fizz \"\r\n180 a=a+1\r\n190 #=30\r\n#=1\r\n";
		Controls.AddRange(new Control[] {
			bo1
		});
		Button btn1 = new Button();
		btn1.Location = new Point(50, 20);
		btn1.Text = "run";
		btn1.Click += btn1_Click;
		Controls.AddRange(new Control[] {
			btn1
		});
	}
	void btn1_Click(object sender, System.EventArgs e) {
		run();
	}
	byte READB(byte adr) {
		byte v = ram[adr];
		return v;
	}
	void WRITEB(byte adr, byte data) {
		ram[adr] = data;
	}
	void putchar(byte b) {
		char c = Convert.ToChar(b);
		bo1.Text += c;
	}
	void put(byte b) {
		bo1.Text += b + " ";
	}
	void crlf() {
		putchar(Convert.ToByte('\r'));
		putchar(Convert.ToByte('\n'));
	}
	byte putl(byte pt, byte d) {
		while (READB(pt) != d)
		{
			putchar(READB(pt++));
		}
		return pt;
	}
	void putlp(byte d) {
		while (READB(Ptr) != d)
		{
			putchar(READB(Ptr++));
		}
	}
	void term() {
		byte cc;
		cc = READB(Ptr++);
		byte val2 = val;
		factr();
		if (cc == Convert.ToByte('*'))
		{
			val = Convert.ToByte(val2 * val);
		}
		else if (cc == Convert.ToByte('+'))
		{
			val = Convert.ToByte(val2 + val);
		}
		else if (cc == Convert.ToByte('-'))
		{
			val = Convert.ToByte(val2 - val);
		}
		else if (cc == Convert.ToByte('/'))
		{
			WRITEB(Rmd, Convert.ToByte(val2 % val));
			val = Convert.ToByte(val2 / val);
		}
		else if (cc == Convert.ToByte('='))
		{
			if (val2 == val) val = 1;
			else val = 0;
		}
		else if (cc == Convert.ToByte('^'))
		{
			val = Convert.ToByte(val2 ^ val);
		}
		else if (cc == Convert.ToByte('&'))
		{
			val = Convert.ToByte(val2 & val);
		}
		else if (cc == Convert.ToByte('|'))
		{
			val = Convert.ToByte(val2 | val);
		}
		else if (cc == Convert.ToByte('>'))
		{
			if (val2 >= val) val = 1;
			else val = 0;
		}
		else
		{
			if (val2 < val) val = 1;
			else val = 0;
		}
	}
	void factr() {
		byte cc;
		if (READB(Ptr) == Convert.ToByte('\0'))
		{
			val = 0;
			return;
		}
		if (getnm2()) return;
		cc = READB(Ptr++);
		if (cc == Convert.ToByte('$'))
		{
			Random r = new Random();
			val = Convert.ToByte(r.Next(10));
		}
		else if (cc == Convert.ToByte(':'))
		{
			val = Convert.ToByte('\t');
		}
		else if (cc == Convert.ToByte(';'))
		{
			val = Convert.ToByte('\n');
		}
		else
		{
			Ptr--;
			getvr2();
			val = READB(adr2);
			Ptr++;
		}
	}
	void expr() {
		byte cc;
		factr();
		while ((cc = READB(Ptr)) != Convert.ToByte('\0'))
		{
			term();
		}
		Ptr++;
	}
	void getvr2() {
		byte cc = READB(Ptr);
		if (cc == Convert.ToByte('a')) adr2 = 230;
		else if (cc == Convert.ToByte('#')) adr2 = Pcc;
		else if (cc == Convert.ToByte('b')) adr2 = 231;
		else if (cc == Convert.ToByte('c')) adr2 = 232;
		else if (cc == Convert.ToByte('%')) adr2 = Rmd;
		else adr2 = 230;
	}
	void getvr() {
		c = READB(Ptr);
		if (c == Convert.ToByte('a')) adr = 230;
		else if (c == Convert.ToByte('#')) adr = Pcc;
		else if (c == Convert.ToByte('b')) adr = 231;
		else if (c == Convert.ToByte('c')) adr = 232;
		else adr = 230;
	}
	void ordr() {
		getvr();
		Ptr++;
		Ptr++;
		if (READB(Ptr) == Convert.ToByte('"'))
		{
			Ptr++;
			putlp(Convert.ToByte('"'));
		}
		else
		{
			expr();
			if (c == Convert.ToByte('$'))
			{
			}
			else if (c == Convert.ToByte('?'))
			{
				put(val);
			}
			else
			{
				WRITEB(adr, val);
			}
		}
	}
	byte nxtln(byte pt) {
		for (pt += 1; READB(pt++) != Convert.ToByte('\0'););
		return pt;
	}
	bool fndln() {
		for (Cur = 0; Cur != READB(Bnd); Cur = nxtln(Cur))
		{
			if (READB(Cur) == READB(Pcc)) return true;
		}
		return false;
	}
	bool nxline() {
		for (Cur = 0; Cur != READB(Bnd); Cur = nxtln(Cur))
		{
			if (READB(Cur) > READB(Pcc)) return true;
		}
		return false;
	}
	bool num() {
		if (48 <= (READB(Ptr)) && (READB(Ptr)) <= 57) return true;
		else return false;
	}
	bool getnm2() {
		byte ch;
		if (!num()) return false;
		byte n = 0;
		do
		{
			n *= 10;
			ch = READB(Ptr++);
			n += Convert.ToByte(ch - 48);
		} while (num());
		val = n;
		return true;
	}
	void run() {
		WRITEB(Bnd, 0);
		byte i;
		byte j;
		string str = bo1.Text;
		string[] lines = str.Split(new string[] {
			"\r\n"
		}, StringSplitOptions.None);
		for (i = 0; i < lines.Length; i++)
		{
			if (lines[i].Length < 1) break;
			Ptr = Lbf;
			for (j = 0; j < lines[i].Length; j++)
			{
				WRITEB(Ptr++, Convert.ToByte(lines[i][j]));
			}
			WRITEB(Ptr++, Convert.ToByte('\0'));
			byte ima = 0;
			Ptr = Lbf;
			if (!getnm2())
			{
				Ptr = Lbf;
				WRITEB(Pcc, 0);
				for ( ; ; )
				{
					ima = READB(Pcc);
					ordr();
					if (READB(Pcc) == 0 && ima == 0)
					{
						break;
					}
					else
					{
						if (READB(Pcc) == 0) WRITEB(Pcc, ima);
						if (READB(Pcc) == 1) ima = 1;
						if (READB(Pcc) == ima)
						{
							if (nxline())
							{
								WRITEB(Pcc, READB(Cur));
								Ptr = Convert.ToByte(Cur + 2);
							}
							else
							{
								break;
							}
						}
						else
						{
							if (fndln())
							{
								WRITEB(Pcc, READB(Cur));
								Ptr = Convert.ToByte(Cur + 2);
							}
							else
							{
								break;
							}
						}
					}
				}
			}
			else
			{
				if (val == 0)
				{
					byte pt;
					for (pt = 0; pt < READB(Bnd); pt++)
					{
						put(READB(pt));
						pt += 1;
						pt = putl(pt, Convert.ToByte('\0'));
						crlf();
					}
				}
				else
				{
					byte src,
						dst,
						m,
						h;
					byte f = 0;
					WRITEB(Pcc, val);
					if (fndln())
					{
						src = nxtln(Cur);
						for (dst = Cur; src != READB(Bnd); dst++, src++)
						{
							WRITEB(dst, READB(src));
						}
						WRITEB(Bnd, dst);
					}
					if (nxline())
					{
						f = 1;
					}
					src = READB(Bnd);
					for (m = 2, h = Ptr; READB(h) != Convert.ToByte('\0'); m++)
					{
						h++;
					}
					if (m > 2)
					{
						WRITEB(Bnd, Convert.ToByte(src + m));
						if (f == 1)
						{
							Cur--;
							for (dst = READB(Bnd); src != Cur; dst--, src--)
							{
								WRITEB(dst, READB(src));
							}
							src++;
						}
						WRITEB(src, val);
						src += 1;
						byte k;
						for (k = 1; k < m; k++)
						{
							WRITEB(src++, READB(Ptr++));
						}
					}
				}
			}
		}
	}
	[STAThread]
	public static void Main() {
		Application.Run(new form1());
	}
}





```


以上。