⚠️ Warning: This is a draft ⚠️

This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.

If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.

M2000 Interpreter



MODULE LIB1 {
      Class ParserClass {
      Private:
            Class bStream {
                  Private:
                  cnt, Buffer A
                  Public:
                  Value (&c) {Try {c=eval(.A, .cnt) : .cnt++:=true}}
                  Class:
                  Module Final bStream (a$){
                        Buffer .A as Integer*Len(a$)
                        Return .A, 0:=a$
                  }
            }
            Func=Lambda->false
            char=0
            obj=Stack
            Function Final IsId {
                  If .char=34 Then =.IsString(false)
            }
            Function Final IsTrue {
                  If .char=0x74 Then If .func() Then If .char=0x72 Then If .func() Then If .char=0x75 Then If .func() Then If .char=0x65 Then PushIt() : =True
                  Sub PushIt()
                        Stack .obj {
                              Push .Boolean(True)
                        }
                  End Sub
            }
            Function Final IsFalse {
                  If .char=0x66 Then If .func() Then If .char=0x61 Then If .func() Then If .char=0x6c Then If .func() Then If .char=0x73 Then If .func() Then If .char=0x65 Then PushIt() : =True
                  Sub PushIt()
                        Stack .obj {
                              Push .Boolean(False)
                        }
                  End Sub
            }
            Function Final IsNull {
                  If .char=0x6e Then If .func() Then If .char=0x75 Then If .func() Then If .char=0x6c Then If .func() Then If .char=0x6c Then PushIt() : =True
                  Sub PushIt()
                        Stack .obj {
                              Push .Null()
                        }
                  End Sub
            }
            Function Final IsSemiCol {
                    If .char=0x3a Then =true
            }
            Function Final IsComma {
                    If .char=0x2c Then =true
            }
            Function Final IsObject {
                  If .char=123 Else exit
                  inventory objinv
                 Stack .obj { Push .Object(objinv)}
                 .Trim
                 While .IsId() {
                       .Trim
                       If .IsSemiCol() Then {
                             .Trim
                             If .IsValue() Then {
                                   Stack .obj {
                                          Shift 2: Append objinv, Letter$:=Group
                                    }
                              }
                       } Else Exit
                       .Trim
                        If not .IsComma() Then exit
                       .Trim
                  }
                  If .char=125 Then { =true } Else .obj<=Stack : .func<=lambda->0
            }
            Function Final IsValue {
                  If .IsString(True) Then {
                         =True
                  } Else.if .IsNumber() Then {
                        =True
                  } Else.If .IsTrue() Then {
                        =True
                  }  Else.If .IsFalse() Then {
                        =True
                  } Else.If .IsNull() Then {
                        =True
                  } Else.if .IsArray() Then {
                        =True
                  } Else.if .IsObject() Then {
                        =True
                  } Else {
                        Print "what", .char
                        Stack .obj { Stack}
                        .func<=lambda->0
                  }
            }
            Function Final Digits (private_stack){
                  While .func() {
                        Select Case .char
                        Case 48 to 57
                        {
                              =true
                             Stack private_stack { Data .char}
                        }
                        Else
                             break
                        End Select
                  }    
            }
            Function Final IsNumber {
                  a=Stack
                  Select Case .char
                  Case 45 ' -
                  {
                              oldfunc=.func
                              Stack a { Data .char}
                              If .Func() Then {
                                    Select Case .char
                                    Case 48
                                    {
                                            Stack a { Data .char}
                                            If .func() Then {
                                                If .char=46 Then {
                                                      Fraction()
                                                      Exponent()
                                                }
                                          }
                                    }
                                    Case 49 to 57
                                    {
                                          Stack a { Data .char}
                                          If .Digits(a) Then {}
                                          Fraction()
                                          Exponent()
                                    }
                                    Else
                                          a=stack
                                    End Select
                              }
                  }
                  Case 48
                  {
                        oldfunc=.func
                        Stack a { Data .char}
                        If .func() Then {
                            If .char=46 Then {
                                  Fraction()
                                  Exponent()
                            }
                      }
                  }
                  Case 49 to 57
                  {
                              oldfunc=.func
                              Stack a { Data .char}
                              If .Digits(a) Then {}
                              Fraction()
                              Exponent()
                  }
                  End Select

                  If len(a)>0 Then {
                        b=each(a)
                        Document D$
                        While b {
                              D$=chrcode$(StackItem(b))
                        }
                        .func<=oldfunc
                        If len(D$)>1 Then For i=2 to len(D$) { .Trim}
                        Stack .obj { Push .Numeric(D$) }
                        =True
                  }
                  '  here is an auto exit from function. Sub as command is an exit
                  Sub Fraction()
                        If .char=46 Then Stack a { Data .char}
                        If .Digits(a) Then { }
                  End Sub
                  Sub Exponent()
                        If .char=101 or .char=61 Then {
                              Stack a { Data .char}
                              If .func() Then {
                                    If .char=43 or .char=45 Then {
                                          Stack a { Data .char }
                                          If .Digits(a) Else {
                                                a=Stack
                                          }
                                    }  Else.If .char>47 and .char<58 Then {
                                          Stack a { Data .char}
                                          If .Digits(a) Then {}
                                    }   Else { a=Stack }
                              }
                        }
                  End Sub
            }
            Function Final IsString (as_object){
            If .char=34 Else exit
                  Document D$
                  While .func() {
                        If .char=34 Then 2000
                        If .char=92 Then {
                              ' special care
                              If .func() Then {
                                    Select Case .Char
                                    Case 117 'u
                                    GetHex()
                                    Case 114 ' r
                                    .char<=0x0d
                                    Case 110 ' n
                                    .char<=0x0a
                                    Case 116 ' t
                                    .char<=0x09
                                    Case 98 ' b
                                    .char<=0x08
                                    Case 102 ' f
                                    .char<=0x0c
                                    Case 0x22, 0x2f , 0x5c
                                    rem  ' need a line always - revision 4
                                    Else
                                    Exit   ' not normal
                                    End Select
                              }
                        }
                        D$=chrcode$(.char)
                  }
                  Exit
      2000 Stack .obj {
                  Print D$
                        If as_object Then {Push .JString$(D$)} Else Push D$
                  } : =True
                  Sub GetHex()
                        Local D$
                        Document D$="0x"
                        For i=1 to 4 {
                              If .func() Then {
                                    If Chrcode$(.char) ~ "[0123456789ABCDEFabcdef]"  Then {
                                          D$=Chrcode$(.char)
                                    } Else 3000
                              }
                        }
                        If i<>5 Then 3000
                        .Char<=Eval(D$)
      3000 End Sub
            }
            Function Final IsArray {

                  If .char=91 Else exit
                  Dim Gr()
                  .Trim
                  If .char=93 Then =true : Stack .obj { Push .Arr(Gr())} : exit
                        While .IsValue() {
                              Stack .obj {
                                    Dim Gr(Len(Gr())+1)
                                    Gr(len(Gr())-1)=Group
                              }
                              .Trim
                              If not .IsComma() Then exit
                              .Trim
                        }
                  If .char=93 Then { =true : Stack .obj { Push .Arr(Gr())} } Else .Func<=lambda->false
            }
            Module Final Trim {
                  While .func() {
                         If .char<33 or .char=160 Else exit
                  }
            }
            Function Final IsContainer {
                 .Trim
                 Select Case chrcode$(.char)
                 Case "{"
                        =.IsObject()
                 Case "["
                        =.IsArray()
                 end select
            }
            Module Final ReadArrayItem (temp, object){
                   Select Case temp.type$
                        Case "String","Boolean","Number", "Null"
                        {
                              If object Then Error "No object "+quote$(temp.type$)
                              Push temp.str$
                        }
                        Case "Object"
                        {
                              If not Empty Then {
                                 Call .ReadObject temp, object, letter$
                              } Else {
                                    If object Then Push Temp : exit
                                    Push .ser$(group(temp),0)
                              }
                        }
                        Case "Array"
                        {
                              If not Empty Then {
                                    ' recursion only with Call statement for modules
                                    Call .ReadArrayItem, Array(temp, number), object
                              } Else {
                                    If object Then Push Temp : exit
                                    Push .ser$(group(temp),0)
                              }
                        }
                        End Select
            }
            Module Final ReadObject (json, object){
                  If type$(json)="Inventory" Then {
                        If exist(json, Letter$) Then {
                              temp=eval(json)
                        } Else {
                             push "none"
                             Break  ' exit Module Final  (Break do something Else in Select End Select)
                        }
                  } Else temp=json
                        Select Case temp.type$
                        Case "String","Boolean","Number", "Null"
                        {
                              If object Then Error "No object "+quote$(temp.type$)
                              Push temp.str$
                        }
                        Case "Object"
                        {
                              If not Empty Then {
                                    Call .ReadObject temp, object
                              } Else {
                                    If object Then Push Temp : exit
                                    Push .ser$(group(temp),0)
                              }
                        }
                        Case "Array"
                        {
                              If not Empty Then {
                                    Call .ReadArrayItem array(temp, number), object
                              } Else {
                                    If object Then Push Temp : exit
                                    Push .ser$(group(temp),0)
                              }
                        }
                        End Select
            }
            Module Final Worker (object){
                         If match("IN") Or match("IS") Then {
                               Push object : ShiftBack 2
                              .ReadObject
                        } Else {
                              read Temp
                              If Type$(Temp)="mArray" Then {
                                    If not Empty Then {
                                          Call .ReadArrayItem, Array(Temp, number), object
                                    } Else {
                                          If object Then Push Temp : exit
                                          Push .ser$(Temp,0)
                                    }
                              } Else {
                                    If not Empty Then {
                                                Call .ReadObject Temp, object
                                    } Else {
                                          If not Empty Then {
                                                Call .ReadObject Temp, object
                                          } Else {
                                                If object Then Push Temp : exit
                                                If Type$(Temp)="Inventory" Then {
                                                      Push .ser$(.Object(Temp),0)
                                                } Else {
                                                      Push .ser$(group(Temp),0)
                                                }
                                          }
                                    }
                              }
                        }
            }
      Public:
            Class Arr {
            Private:
                  MyValue
            Public:
                  Property Type$ {Value} ="Array"
                  Value {
                        =.MyValue
                  }
            Class:
                  Module Final Arr (.MyValue) {}
            }
            Class Null {
                 Property Type$ {Value} ="Null"
                 Property Str$ {Value}="null"
                 Value { =0}
            }
            Class JString$ {
            Private:
                  MyValue$=""
            Public:
                  Property Type$ {Value} ="String"
                  Property Str$ {
                        Value{
                              Link parent MyValue$ to MyValue$
                              value$=quote$(string$(MyValue$ as json))
                        }
                  }
                  Value {
                        =.MyValue$
                  }
            Class:
                  Module Final JString (.MyValue$) {}
            }
            Class Numeric {
            Private:
                  MyValue$=""
            Public:
                  Property Type$ {Value} ="Number"
                  Property Str$ {
                        Value{
                              Link parent MyValue$ to MyValue$
                              value$=MyValue$
                        }
                  }
                  Value {
                        =Val(.MyValue$)
                  }
            Class:
                  Module Final Numeric {
                  If match("S") Then {
                        Read .MyValue$
                  } Else {
                        .Myvalue$<=trim$(str$(Number, 1033))
                  }
                  }
            }
            Class Boolean {
            Private:
                  MyValue=false
            Public:
                  Property Type$ {Value} ="Boolean"
                  Property Str$ {
                        Value{
                              Link parent MyValue to MyValue
                              If MyValue Then {
                                    value$="true"
                              } Else value$="false"
                        }
                  }
                  Value {
                        =.MyValue
                  }
            Class:
                  Module Final Boolean (.MyValue) {}
            }
            Class Object {
            Private:
                  Inventory MyValue
            Public:
                  Property Type$ {Value} ="Object"
                  Value {
                        =.MyValue
                  }
            Class:
                  Module Final Object (.MyValue) {}
            }
            Group Ser$
            Module Final SetSpace (.ser.space) {
            }
            Function Final UseDecimalPoint$ {
                  =str$(val(letter$),"")
            }
            Function Final ReadNumber$ {
                        .Worker false
                        =.UseDecimalPoint$( Letter$)
            }           
            Function Final ReadAnyString$ {
                        .Worker false
                        =Letter$
            }
            Function Final ReadAny {
                        .Worker true
                        Read A
                        =A
            }
            Function Final Eval {
                   .func<=Lambda z=.bStream(Letter$) -> {
                         link .char to c
                         =z(&c)
                   }
                  Stack .obj { Flush}
                  .char<=0
                  If .IsContainer() Then {
                        =StackItem(.obj)
                        .obj<=Stack
                  } Else {
                        inventory emptinv
                        =.Object(emptinv)
                  }
            }
            Group StringValue$ {
                  Add=false
                  Del=false
                  Set (temp) {
                        Read temp1
                        If type$(temp)<>"Group" Then error "Need a group"
                        If not valid(temp.type$="") Then error "not a proper group"
                        If not valid(temp1.type$="") Then error "not a proper group for value"
                        Link parent Null() to MyNull()
                        Null=MyNull()
                        Dim Base 1, A(1)
                        b=(,) : Link b to bb()
                        A(1)=Group(temp)
                        Do {
                              again=false
                              Select Case A(1).type$
                              Case "Array"
                              {
                                    If match("N") Then {
                                          Read where
                                          If len(A(1))<=where and Empty Then {
                                                If .add and not .del Then {
                                                cursize=Len(A(1))
                                                b=A(1) ' A(1) has a pointer so now b has the same pointer
                                                Dim bb(where+1) ' need one more because all "automatic arrays" have base 0
                                                Stock bb(cursize) sweep Len(b)-cursize, Group(Null)
                                                } Else Error "Index out of limits"+str$(where)
                                          } Else If where<0 Then Error "Index out of limits "+str$(where)
                                          If Empty Then {
                                                If .del Then {
                                                      cursize=Len(A(1))
                                                      b=A(1) ' A(1) has a pointer so now b has the same pointer
                                                      If where<cursize-1 Then {
                                                            Stock bb(where+1) Keep cursize-where, bb(where)
                                                      }
                                                      Dim bb(cursize-1) ' bb(0) is an empty array
                                                } Else Return A(1), where:=Group(temp1)
                                          } Else {
                                                A(1)=Array(A(1),where)
                                                again=True
                                          }
                                    } Else Error "No Index Found"
                              }
                              Case "Object"
                              {
                                    If match("S") Then {
                                          Read k$
                                          If Exist(A(1), k$) Then {
                                                If Empty Then {
                                                      If .del Then {
                                                           Delete A(1) , k$
                                                      } else {
                                                            Return A(1), k$:=Group(temp1)
                                                      }
                                                } Else {
                                                      A(1)=Eval(A(1))
                                                      again=True
                                                }
                                        } else.if .add and not .del Then {
                                                 If Empty Then {
                                                            Append A(1), k$:=Group(temp1)
                                                } Else Error "No such Tag "+k$
                                          } Else Error "No such Tag "+k$
                                    } Else Error "No Tag Found"
                              }
                              End Select
                        } until not again
                  }
                  Value (temp) {
                        If type$(temp)<>"Group" Then error "Need a group"
                        If not valid(temp.type$="") Then error "not a proper group"
                        Dim Base 1, A(1)
                        A(1)=Group(temp)
                        Do {
                              again=false
                              Select Case A(1).type$
                              Case "String", "Number", "Null", "Boolean"
                                    Exit
                              Case "Array"
                              {
                                    If match("N") Then {
                                          A(1)=Array(A(1), Number)
                                    } Else Error "No Index Found"
                                    again=True
                              }
                              Case "Object"
                              {
                                    If match("S") Then {
                                          If Exist(A(1), Letter$) Then {
                                                A(1)=Eval(A(1))
                                          } Else Error "No such Tag"
                                    } Else Error "No Tag Found"
                                    again=True
                              }
                              End Select
                        } until not again
                         =A(1).str$
                  }
            }
      Class:
            Class CreatSerialize$ {
            Private:
                  usen=0
                  n=0
                  nl1$={
                  }
                  Function Final Jarray$ (json1, n){
                        A=json1
                        nl$=.nl1$
                        If .usen>0 Then {
                              nl$=nl$+string$(" ", n+.space)
                        }
                        document a$
                        a$="["
                        If Len(A)>0 Then {
                              If .usen>0 Then a$=nl$
                               k=each(A)
                               M=len(A)-1
                               while k {
                                    For This {
                                          Temp=array(k)
                                          select Case temp.type$
                                          Case "Number", "Null","Boolean", "String"
                                          a$=temp.str$
                                          Case "Array"
                                          {
                                                nn=0
                                                If .usen>0 Then {
                                                      nn=n +.space
                                                }
                                                a$=.Jarray$(Temp, nn, "")
                                          }
                                          Case "Object"
                                          {
                                               nn=0
                                                If .usen>0 Then {
                                                      nn=n +.space
                                                }
                                                a$=.Jobject$(Temp, nn,"")
                                          }
                                          Else
                                                a$=" "+temp.type$
                                          end select
                                           If k^<M Then {
                                               a$=", "
                                                If .usen>0 Then a$=nl$
                                          } Else {
                                                If .usen>0 Then a$=.nl1$
                                          }
                                    }
                              }
                        }  else If .usen>0 Then a$=.nl1$
                         If .usen>0 Then a$=string$(" ", n)
                  a$="]"
                     =a$+letter$
                  }
                  Function Final Jobject$ (json1, n){
                                    json=json1
                                    nl$=.nl1$
                                    If .usen>0 Then {
                                          nl$=nl$+string$(" ", n+.space)
                                    }
                                    document a$
                                    a$="{"
                                    If .usen>0 Then a$=nl$
                                     k=each(json)
                                     M=len(json)-1
                                     while k {
                                          a$=quote$(eval$(json, k^)) +" : "
                                          select Case json(k^!).type$
                                          Case "Array"
                                          {
                                                nn=0
                                                If .usen>0 Then {
                                                      nn=n +.space
                                                }
                                                a$=.Jarray$(eval(k), nn, "")
                                          }
                                          Case  "Boolean", "Null", "Number", "String"
                                                a$=json(k^!).str$
                                          Case "Object"
                                          {
                                                nn=0
                                                If .usen>0 Then {
                                                      nn=n +.space
                                                }
                                                a$=.Jobject$(eval(k), nn, "")
                                          }
                                          Else
                                                a$=" "+json( k^!).type$
                                          end select
                                           If k^<M Then {
                                               a$=", "
                                                If .usen>0 Then a$=nl$
                                          } Else {
                                                If .usen>0 Then a$=.nl1$
                                          }
                                    }
                               If .usen>0 Then a$=string$(" ", n)
                              a$="}"
                              =a$+letter$
                  }
                  Class Object {
                  Private:
                        Inventory MyValue
                  Public:
                        Property Type$ {Value} ="Object"
                        Value {
                              =.MyValue
                        }
                  Class:
                        Module Final Object (.MyValue) {}
                  }
            Public:
                  space=10
                  Value (json, n) {
                              a$=.nl1$
                              b$=""
                              .usen<=n
                              n--
                              If n<=0 Then { a$="" : n=0 } Else b$=string$(" ", n)
                              If type$(json)<>"Group" Then {
                                    If type$(json)="Inventory" Then {
                                          =b$+.Jobject$(.Object(json),n, a$)
                                    } else.if type$(json)="mArray" Then {
                                          =b$+.Jarray$(json, n, a$)
                                    }
                              } Else {
                                    If json.type$="Object" Then {
                                          =b$+.Jobject$(json, n,a$)
                                    } else.if json.type$="Array" Then {
                                          =b$+.Jarray$(json, n, a$)
                                    }
                              }
                  }
            }
            Module Final ParserClass {
                  Let .Ser=.CreatSerialize$()
            }
      }
}