Ada: step1 with opentoken
[jackhill/mal.git] / ada / reader.adb
CommitLineData
673ee61c
CM
1with Ada.IO_Exceptions;
2with Ada.Characters.Latin_1;
3with Ada.Strings.Maps.Constants;
4with Ada.Strings.Unbounded;
5with Ada.Text_IO;
6with Opentoken.Recognizer.Character_Set;
7with Opentoken.Recognizer.Identifier;
8with Opentoken.Recognizer.Integer;
9with Opentoken.Recognizer.Keyword;
10with Opentoken.Recognizer.Line_Comment;
11with Opentoken.Recognizer.Separator;
12with Opentoken.Recognizer.Single_Character_Set;
13with Opentoken.Recognizer.String;
14with OpenToken.Text_Feeder.String;
15with Opentoken.Token.Enumerated.Analyzer;
16
17package body Reader is
18
19 type Lexemes is (Int, Sym,
20 Nil, True_Tok, False_Tok, Exp_Tok,
21 Str, Atom,
22 Whitespace, Comment);
23
24 package Lisp_Tokens is new Opentoken.Token.Enumerated (Lexemes);
25 package Tokenizer is new Lisp_Tokens.Analyzer;
26
27 Exp_Recognizer : constant Tokenizer.Recognizable_Token :=
28 Tokenizer.Get(Opentoken.Recognizer.Separator.Get ("**"));
29
30 Nil_Recognizer : constant Tokenizer.Recognizable_Token :=
31 Tokenizer.Get(Opentoken.Recognizer.Keyword.Get ("nil"));
32
33 True_Recognizer : constant Tokenizer.Recognizable_Token :=
34 Tokenizer.Get(Opentoken.Recognizer.Keyword.Get ("true"));
35
36 False_Recognizer : constant Tokenizer.Recognizable_Token :=
37 Tokenizer.Get(Opentoken.Recognizer.Keyword.Get ("false"));
38
39 ID_Recognizer : constant Tokenizer.Recognizable_Token :=
40 Tokenizer.Get(Opentoken.Recognizer.Identifier.Get);
41
42 Int_Recognizer : constant Tokenizer.Recognizable_Token :=
43 Tokenizer.Get(Opentoken.Recognizer.Integer.Get);
44
45 String_Recognizer : constant Tokenizer.Recognizable_Token :=
46 Tokenizer.Get(Opentoken.Recognizer.String.Get);
47
48 -- Atom definition
49 Start_Chars : Ada.Strings.Maps.Character_Set :=
50 Ada.Strings.Maps.Constants.Letter_Set;
51
52 Body_Chars : Ada.Strings.Maps.Character_Set :=
53 Ada.Strings.Maps."or"
54 (Ada.Strings.Maps.Constants.Alphanumeric_Set,
55 Ada.Strings.Maps.To_Set ('-'));
56
57 Atom_Recognizer : constant Tokenizer.Recognizable_Token :=
58 Tokenizer.Get
59 (Opentoken.Recognizer.Identifier.Get (Start_Chars, Body_Chars));
60
61 Lisp_Syms : constant Ada.Strings.Maps.Character_Set :=
62 Ada.Strings.Maps.To_Set ("[]{}()'`~^@+-*/");
63
64 Sym_Recognizer : constant Tokenizer.Recognizable_Token :=
65 Tokenizer.Get (Opentoken.Recognizer.Single_Character_Set.Get (Lisp_Syms));
66
67 Lisp_Whitespace : constant Ada.Strings.Maps.Character_Set :=
68 Ada.Strings.Maps.To_Set (Ada.Characters.Latin_1.HT &
69 Ada.Characters.Latin_1.Space &
70 Ada.Characters.Latin_1.Comma);
71
72 Whitesp_Recognizer : constant Tokenizer.Recognizable_Token :=
73 Tokenizer.Get (Opentoken.Recognizer.Character_Set.Get (Lisp_Whitespace));
74
75 Comment_Recognizer : constant Tokenizer.Recognizable_Token :=
76 Tokenizer.Get(Opentoken.Recognizer.Line_Comment.Get (";"));
77
78 Syntax : constant Tokenizer.Syntax :=
79 (Int => Int_Recognizer,
80 Sym => Sym_Recognizer,
81 Nil => Nil_Recognizer,
82 True_Tok => True_Recognizer,
83 False_Tok => False_Recognizer,
84 Exp_Tok => Exp_Recognizer,
85 Str => String_Recognizer,
86 Atom => Atom_Recognizer,
87 Whitespace => Whitesp_Recognizer,
88 Comment => Comment_Recognizer --,
89 );
90
91 Input_Feeder : aliased OpenToken.Text_Feeder.String.Instance;
92
93 Analyzer : Tokenizer.Instance :=
94 Tokenizer.Initialize (Syntax, Input_Feeder'access);
95
96
97 function Get_Token_String return String is
98 begin
99 return Tokenizer.Lexeme (Analyzer);
100 end Get_Token_String;
101
102
103 function Get_Token_Char return Character is
104 S : String := Tokenizer.Lexeme (Analyzer);
105 begin
106 return S(S'First);
107 end Get_Token_Char;
108
109
110 function Get_Token return Types.Mal_Type_Access is
111 Res : Types.Mal_Type_Access;
112 begin
113 Tokenizer.Find_Next (Analyzer);
114 case Tokenizer.ID (Analyzer) is
115 when Int =>
116 Res := new Types.Mal_Type'
117 (Sym_Type => Types.Int,
118 Int_Val => Integer'Value (Get_Token_String));
119 when Sym =>
120 Res := new Types.Mal_Type'
121 (Sym_Type => Types.Sym, Symbol => Get_Token_Char);
122 when Nil =>
123 Res := new Types.Mal_Type'
124 (Sym_Type => Types.Atom,
125 The_Atom => Ada.Strings.Unbounded.To_Unbounded_String
126 (Get_Token_String));
127 when True_Tok =>
128 Res := new Types.Mal_Type'
129 (Sym_Type => Types.Atom,
130 The_Atom => Ada.Strings.Unbounded.To_Unbounded_String
131 (Get_Token_String));
132 when False_Tok =>
133 Res := new Types.Mal_Type'
134 (Sym_Type => Types.Atom,
135 The_Atom => Ada.Strings.Unbounded.To_Unbounded_String
136 (Get_Token_String));
137 when Exp_Tok =>
138 Res := new Types.Mal_Type'
139 (Sym_Type => Types.Atom,
140 The_Atom => Ada.Strings.Unbounded.To_Unbounded_String
141 (Get_Token_String));
142 when Str =>
143 Res := new Types.Mal_Type'
144 (Sym_Type => Types.Str,
145 The_String => Ada.Strings.Unbounded.To_Unbounded_String
146 (Get_Token_String));
147 when Atom =>
148 Res := new Types.Mal_Type'
149 (Sym_Type => Types.Atom,
150 The_Atom => Ada.Strings.Unbounded.To_Unbounded_String
151 (Get_Token_String));
152 when Whitespace | Comment => null;
153 end case;
154 return Res;
155 end Get_Token;
156
157
158 -- Parsing
159 function Read_Form return Types.Mal_Type_Access;
160
161 function Read_List return Types.Mal_Type_Access is
162 use types;
163 List_MT, MTA : Types.Mal_Type_Access;
164 begin
165 List_MT := new Types.Mal_Type'
166 (Sym_Type => Types.List,
167 The_List => Types.Lists.Empty_List);
168 loop
169 MTA := Read_Form;
170 exit when MTA = null or else
171 MTA.all = (Sym_Type => Sym, Symbol => ')');
172 Types.Lists.Append (List_MT.The_List, MTA);
173 end loop;
174 return List_MT;
175 end Read_List;
176
177
178 function Read_Form return Types.Mal_Type_Access is
179 use Types;
180 MT : Types.Mal_Type_Access;
181 begin
182 MT := Get_Token;
183 if MT.all = (Sym_Type => Sym, Symbol => '(') then
184 return Read_List;
185 else
186 return MT;
187 end if;
188 end Read_Form;
189
190
191 function Read_Str (S : String) return Types.Mal_Type_Access is
192 begin
193 Analyzer.Reset;
194 Input_Feeder.Set (S);
195 return Read_Form;
196 exception
197 when OPENTOKEN.SYNTAX_ERROR =>
198 Ada.Text_IO.Put_Line
199 (Ada.Text_IO.Standard_Error,
200 "Lexical error at char " & Integer'Image (Analyzer.Line));
201 raise Ada.IO_Exceptions.End_Error;
202 end Read_Str;
203
204
205end Reader;