パソコン活用研究5番街(Visual
Basic、Excel(VBA)、BASIC プログラミング研究)
VB.NETで計算機を作る(足し算引き算)
(準備中)
いよいよVB.NETで再帰を使って再帰下降パースによる演算を実装してみることにしますが。
まずは肩慣らしで足し算と引き算のみでやってみます。
※まだ、足し算、引き算にしか対応させていないので、乗算除算、括弧( )があると停止します。
自分の勉強用にコーディングしたものなので、ボロな個所が多数あります。
Cによる完成形のプログラムは「プログラミング言語を作る」のP57〜P70にあります。
本に掲載されているプログラムは、再帰下降パーサによる完成されたプログラムで、
字句解析ー>構文解析ー>演算まで2段抜かしでやってしまうようなプログラムです。
このページでは、各プロセスの動きを1段づつ確認したいので、本にあるような洗練されたものとはかなり違う
無骨なプログラムを作っていきます。加えて、上に書いたように乗算除算、括弧(
)は対応してないので未完成形です。
ソースコード
Imports System Module Program
REM Public num_token As Integer
Enum type number add_op sub_op mul_op div_op lparen rparen space bad line_end End Enum
Structure token Dim type As type Dim str As String Dim v As Integer End Structure
Public tok(20) As token
Sub Main(args As String()) Dim i, pos, isnum As Integer Dim value As Double Dim r As type Dim statement As String statement = Console.ReadLine()
For i = 0 To statement.Length - 1 Console.WriteLine("{0} : {1}", i, statement.Chars(i)) Next
Console.WriteLine("TOKEN") pos = 0 : isnum = 0
For i = 0 To statement.Length - 1 r = checktype(statement.Chars(i)) If r = type.space Then GoTo L1 : If r = type.bad Then Exit For If isnum = 1 And r = type.number Then tok(pos).str = tok(pos).str + statement.Chars(i) : tok(pos).v = Integer.Parse(tok(pos).str) : GoTo L1 If isnum = 1 And r = type.rparen Then pos = pos + 1 : tok(pos).str = statement.Chars(i) : tok(pos).type = r : GoTo L1 If isnum = 1 And (r = type.add_op Or r = type.sub_op Or r = type.mul_op Or r = type.div_op) Then pos = pos + 1 : tok(pos).str = statement.Chars(i) : tok(pos).type = r : pos = pos + 1 : isnum = 0 : GoTo L1 If isnum = 0 And r = type.lparen Then tok(pos).str = tok(pos).str + statement.Chars(i) : tok(pos).type = r : pos = pos + 1 : GoTo L1 If isnum = 0 And r = type.number Then tok(pos).str = tok(pos).str + statement.Chars(i) : tok(pos).type = type.number : tok(pos).v = Integer.Parse(tok(pos).str) : isnum = 1 If isnum = 0 And r = type.sub_op Then tok(pos).str = tok(pos).str + statement.Chars(i) : tok(pos).type = type.number : isnum = 1 L1: Next
tok(pos + 1).type = type.line_end
For i = 0 To pos + 1 Console.WriteLine("{0}: {1} : {2} : {3}", i, tok(i).str, tok(i).type, tok(i).v) Next
If r = type.bad Then Console.WriteLine("Wrong expression") Console.WriteLine("Calculate") value = expression() Console.WriteLine(value) End Sub
Function expression() As Double Dim v1, v2 As Double Dim t As token v1 = primary_expression() Console.WriteLine("expression v1:{0}", v1) While (1) t = get_token() Console.WriteLine("expression {0}: {1} : {2} ", t.str, t.type, t.v) If (t.type <> type.add_op And t.type <> type.sub_op) Then unget_token() : Exit While v2 = primary_expression() Console.WriteLine("expression v2:{0}", v2) If t.type = type.add_op Then v1 = v1 + v2 If t.type = type.sub_op Then v1 = v1 - v2 Console.WriteLine("expression calculated v1:{0}", v1) End While
Return v1 End Function
Function primary_expression() As Double Dim t As token t = get_token() Console.WriteLine("primary_expression {0}: {1} : {2} ", t.str, t.type, t.v) If t.type = type.number Then Return t.v Else Console.WriteLine("Syntax error") : End
End Function
Function get_token() As token Static Dim i As Integer = 0 Console.WriteLine("get_token {0}: {1} : {2} :{3} ", i, tok(i).str, tok(i).type, tok(i).v) REM Console.WriteLine("get_token {0}: {1} : {2} :{3} ", num_token, t.str, t.type, t.v) i = i + 1 Return tok(i - 1) End Function
Sub unget_token()
End Sub
Function checktype(ByVal t As String) As Integer If IsNumeric(t) = True Then Return type.number If t = "+" Then Return type.add_op If t = "-" Then Return type.sub_op If t = "*" Then Return type.mul_op If t = "/" Then Return type.div_op If t = "(" Then Return type.lparen If t = ")" Then Return type.rparen If t = " " Then Return type.space Return type.bad End Function
End Module
TopPage > Visual BasIc&Excel活用研究目次