A really simple interpreter with 26 variables, a to z. It handles expressions with +, -, * and /. Multiply and divide is done before + and - of course. You can also use parenthesis to force a part of an expression to be evaluated first.
There are two legal statements: Assignment and output. An assignment statement has the form variable = expression.
The output statement has the form ?variable.
If people really want it I can probably also add support for:
Strict variable declaration (à la option explicit).
Multi-character variables
Math functions (sin, cos, whatever)
Boolean operators (that actually works, like AND and NOT.)
So put your vote if you want something done.
Note: It uses integers, no floats, so that 5/2 = 2. (Speaking of which: vote for a modulo operator if you want one.)
Code: Select all
OpenConsole()
#Ind = " "
Global Look.s
Global Dim Table.l(26)
Global Stream.s
;Logical not
; Procedure.l Not(b.l)
; !CMP DWord [ESP], 0
; !JZ l_cl_0
; !XOR eax, eax
; ProcedureReturn
; cl_0:
; !MOV eax, 1
; ProcedureReturn
; EndProcedure
;Cleanup then end
Procedure Finish()
PrintN("Ending.")
Input()
End
EndProcedure
Procedure.s VisibleToken(s.s)
Select s.s
Case #CR$
s.s = "newline (CR)"
Case #LF$
s.s = "newline (LF)"
Case ""
s.s = "nothing"
Default
s.s = "'" + s.s + "'"
EndSelect
ProcedureReturn s.s
EndProcedure
;Report an error
Procedure Error(s.s)
PrintN("Error: "+s+".")
EndProcedure
;Report an error and abort
Procedure Abort(s.s)
Error(s.s)
Finish()
EndProcedure
;Report what was expected
Procedure Expected(expected.s)
Abort("Expected: " + expected + ", got '" + VisibleToken(Look) + "'")
EndProcedure
;Output a tabbed string
Procedure Emit(s.s)
Print(#Ind + s.s)
EndProcedure
;Output a tabbed line with linefeed
Procedure EmitLn(s.s)
Emit(s.s)
PrintN("")
EndProcedure
;Read a character into Look
Procedure GetChar()
Look = Left(Stream,1)
Stream = Right(Stream, Len(Stream)-1)
EndProcedure
;Recognize whitespace
Procedure.b IsWhiteSpace(s.s)
Select s.s
Case " " :
Case #TAB$ :
Default
ProcedureReturn 0
EndSelect
ProcedureReturn 1
EndProcedure
;Eat whitespace
Procedure EatWhite()
While IsWhiteSpace(Look)
GetChar()
Wend
EndProcedure
;Match a specific input character
Procedure Match(s.s)
If Look <> s
Expected("'"+s+"'")
Else
GetChar()
EatWhite()
EndIf
EndProcedure
;Recognize and skip over a newline
Procedure Newline()
If Look = #CR$
GetChar()
If Look = #LF$
GetChar()
EndIf
EndIf
EndProcedure
;Recognize an alpha character
Procedure.b IsAlpha(s.s)
ProcedureReturn Bool((Asc(UCase(s.s)) > 64 And Asc(UCase(s.s)) < 91))
EndProcedure
;Recognize an addop
Procedure.b IsAddop(s.s)
ProcedureReturn Bool(s.s = "+" Or s.s = "-")
EndProcedure
;Recognize a mulop
Procedure.b IsMulop(s.s)
ProcedureReturn Bool(s.s = "*" Or s.s = "/")
EndProcedure
;Recognize a decimal digit
Procedure.b IsDigit(s.s)
ProcedureReturn Bool(Asc(UCase(s.s)) > 47 And Asc(UCase(s.s)) < 58)
EndProcedure
;Recognize an alphanumeric
Procedure.b IsAlphaNumeric(s.s)
ProcedureReturn Bool(IsAlpha(s.s) Or IsDigit(s.s))
EndProcedure
;Get an identifier
Procedure.s GetName()
If Not(IsAlpha(Look))
Expected("Name")
EndIf
temp.s = UCase(Look)
EatWhite()
GetChar()
EatWhite()
ProcedureReturn temp.s
EndProcedure
;Get a number
Procedure.l GetNum()
Value.l
If Not(IsDigit(Look))
Expected("Integer")
EndIf
While IsDigit(Look)
Value = 10 * Value + Asc(Look)-Asc("0")
GetChar()
Wend
ProcedureReturn Value
EndProcedure
;Read a line into the stream
Procedure ReadLn()
Stream + Input()+#CR$ : PrintN("")
GetChar()
EatWhite()
EndProcedure
;Init
Procedure Init()
ReadLn()
EndProcedure
;------------------------------
Declare.l Expression()
Procedure Outp()
Shared Table()
Match("?")
EmitLn(Str(Table(Asc(GetName())-Asc("A"))))
EndProcedure
Procedure.l Factor()
Value.l
If Look = "("
Match("(")
Value = Expression()
Match(")")
ElseIf IsAlpha(Look)
Value = Table(Asc(GetName())-Asc("A"))
Else
Value = GetNum()
EndIf
ProcedureReturn Value
EndProcedure
Procedure.l Term()
Value.l
Value.l = Factor()
While IsMulop(Look)
Select Look
Case "*"
Match("*")
Value * Factor()
Case "/"
Match("/")
Value / Factor()
EndSelect
Wend
ProcedureReturn Value
EndProcedure
Procedure.l Expression()
Value.l
If IsAddop(Look)
Value = 0
Else
Value = Term()
While IsAddop(Look)
Select Look
Case "+"
Match("+")
Value + Term()
Case "-"
Match("-")
Value - Term()
EndSelect
Wend
EndIf
ProcedureReturn Value
EndProcedure
Procedure Assignment()
Name.s
Name.s = GetName()
Match("=")
Table(Asc(Name.s)-Asc("A")) = Expression()
EndProcedure
Procedure Program()
While Look <> "."
Select Look
Case "?": Outp()
Default : Assignment()
EndSelect
Newline()
ReadLn()
Wend
EndProcedure
Init()
Program()
Finish()