1
1
// lib.rs
2
- use std:: io:: Write ;
2
+ use std:: io:: { self , Write } ;
3
3
use std:: collections:: HashMap ;
4
4
use std:: error:: Error ;
5
+ use log:: * ;
5
6
6
7
#[ derive( Debug , Clone ) ]
7
8
pub enum Token {
@@ -20,6 +21,7 @@ pub enum Token {
20
21
Divide ,
21
22
LParen ,
22
23
RParen ,
24
+ Function ( String ) , // Represents a function invocation like :add
23
25
Open ,
24
26
ReadLines ,
25
27
Clear ,
@@ -30,43 +32,50 @@ impl std::str::FromStr for Token {
30
32
type Err = & ' static str ;
31
33
32
34
fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
33
- match s {
34
- "." => Ok ( Token :: Display ) ,
35
- "+" => Ok ( Token :: Plus ) ,
36
- "-" => Ok ( Token :: Minus ) ,
37
- "*" => Ok ( Token :: Multiply ) ,
38
- "/" => Ok ( Token :: Divide ) ,
39
- "(" => Ok ( Token :: LParen ) ,
40
- ")" => Ok ( Token :: RParen ) ,
41
-
42
- "open" => Ok ( Token :: Open ) ,
43
- "readlines" => Ok ( Token :: ReadLines ) ,
44
- "clear" => Ok ( Token :: Clear ) ,
45
- "listdir" => Ok ( Token :: ListDir ) ,
46
-
47
- "arrnum" => Ok ( Token :: MakeArrayNumberI32 ) ,
48
- "arrtxt" => Ok ( Token :: MakeArrayText ) ,
49
- "join" => Ok ( Token :: Join ) ,
50
- _ => {
51
- if let Ok ( number) = s. parse :: < i32 > ( ) {
52
- Ok ( Token :: NumberI32 ( number) )
53
- } else {
54
- Ok ( Token :: Text ( s. to_string ( ) ) )
55
- }
35
+ debug ! ( "Parsing token: {}" , s) ;
36
+ if s. starts_with ( ':' ) {
37
+ if s. len ( ) == 1 {
38
+ Err ( "Invalid function name" )
39
+ } else {
40
+ Ok ( Token :: Function ( s[ 1 ..] . to_string ( ) ) )
56
41
}
42
+ } else if s == "." {
43
+ Ok ( Token :: Display )
44
+ } else if s == "+" {
45
+ Ok ( Token :: Plus )
46
+ } else if s == "-" {
47
+ Ok ( Token :: Minus )
48
+ } else if s == "*" {
49
+ Ok ( Token :: Multiply )
50
+ } else if s == "/" {
51
+ Ok ( Token :: Divide )
52
+ } else if s == "(" {
53
+ Ok ( Token :: LParen )
54
+ } else if s == ")" {
55
+ Ok ( Token :: RParen )
56
+ } else if s == "clear" {
57
+ Ok ( Token :: Clear )
58
+ } else if s == "listdir" {
59
+ Ok ( Token :: ListDir )
60
+ } else if let Ok ( number) = s. parse :: < i32 > ( ) {
61
+ Ok ( Token :: NumberI32 ( number) )
62
+ } else {
63
+ Ok ( Token :: Text ( s. to_string ( ) ) )
57
64
}
58
65
}
59
66
}
60
67
68
+ #[ derive( Default ) ]
61
69
pub struct Stack {
62
70
items : Vec < Token > ,
71
+ pub functions : HashMap < String , Vec < Token > > , // Stores function definitions
72
+ literal_mode : bool ,
63
73
}
64
74
75
+
65
76
impl Stack {
66
77
pub fn new ( ) -> Stack {
67
- Stack {
68
- items : vec ! [ ] ,
69
- }
78
+ Stack :: default ( )
70
79
}
71
80
72
81
pub fn clear ( & mut self ) {
@@ -79,15 +88,29 @@ impl Stack {
79
88
80
89
pub fn display ( & self ) {
81
90
println ! ( "{}" , self . repr( ) ) ;
91
+ println ! ( "Functions: {:?}" , self . functions) ;
82
92
}
83
93
84
94
pub fn push_str ( & mut self , item : & str ) -> Result < ( ) , Box < dyn Error > > {
85
- match item. parse :: < Token > ( ) {
86
- Ok ( token) => {
87
- self . push ( token) ?;
88
- } ,
89
- Err ( _) => {
90
- self . push ( Token :: Text ( item. to_string ( ) ) ) ?;
95
+ if item. starts_with ( '`' ) && item. len ( ) > 1 {
96
+ // Single-token literal
97
+ self . push ( Token :: Text ( item[ 1 ..] . to_string ( ) ) ) ?;
98
+ } else if item == "`" {
99
+ // Enter literal mode
100
+ self . literal_mode = true ;
101
+ } else if item == "~" && self . literal_mode {
102
+ // Exit literal mode
103
+ self . literal_mode = false ;
104
+ } else if self . literal_mode {
105
+ // Add as literal in literal mode
106
+ self . push ( Token :: Text ( item. to_string ( ) ) ) ?;
107
+ } else {
108
+ match item {
109
+ ":make-fn" => self . make_function ( ) ?,
110
+ _ => match item. parse :: < Token > ( ) {
111
+ Ok ( token) => self . push ( token) ?,
112
+ Err ( _) => self . push ( Token :: Text ( item. to_string ( ) ) ) ?,
113
+ } ,
91
114
}
92
115
}
93
116
Ok ( ( ) )
@@ -104,6 +127,7 @@ impl Stack {
104
127
Token :: Minus => self . subtract ( ) ?,
105
128
Token :: Multiply => self . multiply ( ) ?,
106
129
Token :: Divide => self . divide ( ) ?,
130
+ Token :: Function ( name) => self . call_function ( & name) ?,
107
131
Token :: LParen => todo ! ( ) ,
108
132
Token :: RParen => todo ! ( ) ,
109
133
Token :: Open => todo ! ( ) ,
@@ -118,6 +142,45 @@ impl Stack {
118
142
Ok ( ( ) )
119
143
}
120
144
145
+ fn call_function ( & mut self , name : & str ) -> Result < ( ) , Box < dyn Error > > {
146
+ debug ! ( "Calling function: {}" , name) ;
147
+ if let Some ( definition) = self . functions . get ( name) {
148
+ debug ! ( "Function definition: {:?}" , definition) ;
149
+ for token in definition. clone ( ) {
150
+ let s = match token {
151
+ Token :: Text ( value) => value, // End marker
152
+ _ => return Err ( "Expected a text value" . into ( ) ) ,
153
+ } ;
154
+ let operation = s. parse :: < Token > ( ) ?;
155
+ self . push ( operation) ?;
156
+ }
157
+ Ok ( ( ) )
158
+ } else {
159
+ Err ( format ! ( "Undefined function: {}" , name) . into ( ) )
160
+ }
161
+ }
162
+
163
+ fn make_function ( & mut self ) -> Result < ( ) , Box < dyn Error > > {
164
+ let mut tokens = vec ! [ ] ;
165
+
166
+ // Collect tokens until the stack contains the function name
167
+ while let Some ( token) = self . pop ( ) {
168
+ match token {
169
+ Token :: Text ( value) if value == "~" => break , // End marker
170
+ Token :: Text ( value) => tokens. push ( Token :: Text ( value) ) ,
171
+ _ => return Err ( "Expected a text value" . into ( ) ) ,
172
+ }
173
+ }
174
+ debug ! ( "Function tokens: {:?}" , tokens) ;
175
+
176
+ if let Some ( Token :: Text ( name) ) = tokens. pop ( ) {
177
+ self . functions . insert ( name, tokens) ;
178
+ Ok ( ( ) )
179
+ } else {
180
+ Err ( "Expected a function name" . into ( ) )
181
+ }
182
+ }
183
+
121
184
fn join ( & mut self ) -> Result < ( ) , Box < dyn Error > > {
122
185
if let Some ( Token :: ArrayText ( items) ) = self . pop ( ) {
123
186
let total = items. join ( "" ) ;
@@ -245,5 +308,4 @@ impl Stack {
245
308
output. push ( self . repr ( ) ) ;
246
309
Ok ( output)
247
310
}
248
-
249
311
}
0 commit comments