diff options
| author | Joel Martin <github@martintribe.org> | 2014-11-15 23:15:09 -0600 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2015-01-09 16:16:47 -0600 |
| commit | ee7cd5859e56423983f025088c8cef36b7ed09dd (patch) | |
| tree | da9f2011f4feaa34c96a63407fa4e8720eb1d4dc /vb/reader.vb | |
| parent | c3b508af92800f63bf99f41af68f026535f454f5 (diff) | |
| download | mal-ee7cd5859e56423983f025088c8cef36b7ed09dd.tar.gz mal-ee7cd5859e56423983f025088c8cef36b7ed09dd.zip | |
VB.Net: port of C# version.
Diffstat (limited to 'vb/reader.vb')
| -rw-r--r-- | vb/reader.vb | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/vb/reader.vb b/vb/reader.vb new file mode 100644 index 0000000..121aac2 --- /dev/null +++ b/vb/reader.vb @@ -0,0 +1,181 @@ +Imports System +Imports System.Collections +Imports System.Collections.Generic +Imports System.Text.RegularExpressions +Imports Mal +Imports MalVal = Mal.types.MalVal +Imports MalSymbol = Mal.types.MalSymbol +Imports MalList = Mal.types.MalList +Imports MalVector = Mal.types.MalVector +Imports MalHashMap = Mal.types.MalHashMap +Imports MalThrowable = Mal.types.MalThrowable +Imports MalContinue = Mal.types.MalContinue + +Namespace Mal + Public Class reader + Public Class ParseError + Inherits MalThrowable + Public Sub New(msg As String) + MyBase.New(msg) + End Sub + End Class + + Public Class Reader + Private tokens As New List(Of String) + Private position As Int32 = 0 + Sub New(t As List(Of String)) + tokens = t + position = 0 + End Sub + + Public Function peek() As String + If position >= tokens.Count Then + return Nothing + Else + return tokens(position) + End If + End Function + + Public Function get_next() As String + If position >= tokens.Count Then + return Nothing + Else + position += 1 + return tokens(position-1) + End If + End Function + End Class + + Shared Function tokenize(str As String) As List(Of String) + Dim tokens As New List(Of String) + Dim pattern As String = "[\s ,]*(~@|[\[\]{}()'`~@]|""(?:[\\].|[^\\""])*""|;.*|[^\s \[\]{}()'""`~@,;]*)" + Dim regex As New Regex(pattern) + For Each match As Match In regex.Matches(str) + Dim token As String = match.Groups(1).Value + If Not token Is Nothing _ + AndAlso Not token = "" _ + AndAlso Not token(0) = ";" Then + 'Console.WriteLine("match: ^" & match.Groups[1] & "$") + tokens.Add(token) + End If + Next + return tokens + End Function + + Shared Function read_atom(rdr As Reader) As MalVal + Dim token As String = rdr.get_next() + Dim pattern As String = "(^-?[0-9]+$)|(^-?[0-9][0-9.]*$)|(^nil$)|(^true$)|(^false$)|^("".*"")$|(^[^""]*$)" + Dim regex As Regex = New Regex(pattern) + Dim match As Match = regex.Match(token) + 'Console.WriteLine("token: ^" + token + "$") + If not match.Success Then + throw New ParseError("unrecognized token '" & token & "'") + End If + If match.Groups(1).Value <> String.Empty Then + return New Mal.types.MalInt(Integer.Parse(match.Groups(1).Value)) + Else If match.Groups(3).Value <> String.Empty Then + return Mal.types.Nil + Else If match.Groups(4).Value <> String.Empty Then + return Mal.types.MalTrue + Else If match.Groups(5).Value <> String.Empty Then + return Mal.types.MalFalse + Else If match.Groups(6).Value <> String.Empty Then + Dim str As String = match.Groups(6).Value + return New Mal.types.MalString( + str.Substring(1, str.Length-2) _ + .Replace("\""", """") _ + .Replace("\n", Environment.NewLine)) + Else If match.Groups(7).Value <> String.Empty Then + return New Mal.types.MalSymbol(match.Groups(7).Value) + Else + throw New ParseError("unrecognized '" & match.Groups(0).Value & "'") + End If + End Function + + Shared Function read_list(rdr As Reader, lst As MalList, + start As String, last As String) As MalVal + Dim token As String = rdr.get_next() + If token(0) <> start Then + throw New ParseError("expected '" & start & "'") + End If + + token = rdr.peek() + While token IsNot Nothing AndAlso token(0) <> last + lst.conj_BANG(read_form(rdr)) + token = rdr.peek() + End While + + If token Is Nothing Then + throw New ParseError("expected '" & last & "', got EOF") + End If + rdr.get_next() + + return lst + End Function + + Shared Function read_hash_map(rdr As Reader) As MalVal + Dim lst As MalList = DirectCast(read_list(rdr, new MalList(), + "{", "}"),MalList) + return New MalHashMap(lst) + End Function + + + Shared Function read_form(rdr As Reader) As MalVal + Dim token As String = rdr.peek() + If token Is Nothing Then + throw New MalContinue() + End If + Dim form As MalVal = Nothing + + Select token + Case "'" + rdr.get_next() + return New MalList(New MalSymbol("quote"), + read_form(rdr)) + Case "`" + rdr.get_next() + return New MalList(New MalSymbol("quasiquote"), + read_form(rdr)) + Case "~" + rdr.get_next() + return New MalList(New MalSymbol("unquote"), + read_form(rdr)) + Case "~@" + rdr.get_next() + return new MalList(New MalSymbol("splice-unquote"), + read_form(rdr)) + Case "^" + rdr.get_next() + Dim meta As MalVal = read_form(rdr) + return new MalList(New MalSymbol("with-meta"), + read_form(rdr), + meta) + Case "@" + rdr.get_next() + return new MalList(New MalSymbol("deref"), + read_form(rdr)) + + Case "(" + form = read_list(rdr, New MalList(), "(" , ")") + Case ")" + throw New ParseError("unexpected ')'") + Case "[" + form = read_list(rdr, New MalVector(), "[" , "]") + Case "]" + throw New ParseError("unexpected ']'") + Case "{" + form = read_hash_map(rdr) + Case "}" + throw New ParseError("unexpected '}'") + Case Else + form = read_atom(rdr) + End Select + return form + End Function + + + Shared Function read_str(str As string) As MalVal + return read_form(New Reader(tokenize(str))) + End Function + End Class +End Namespace |
