I'm trying to write a program that accepts user input (one line at a time) and evaluates this user input in some ways.
I have a function getline : unit -> string that reads a string from stdin and returns it. The commands have the following format:
#command1 arg1 arg2 arg3
#cmd2 arg1 arg2
#nextcommand arg1 arg2 arg3 arg4
#quit
#exit
Exemplary calls to the commands could then look as follows:
#command1 2 6 3
#cmd2 6 3
#nextcommand a b3 2 3
The main problem is the function evalcommand : string -> unit that takes a whole line obtained by getline. I started
let evalcommand command = match command with
| "#quit" | "#exit" -> () (* no problem; both length 4 and no arguments *)
| (* how to capture arguments properly? *)
How can I cope with commands whose lengths are differing (such as e.g. command1 and cmd2) and that have additional arguments with them?
Not-so-nice alternatives already considered:
Using a parser (possibly generated by a parser generator): This was the first thing that came to my mind, but since I only want to support five or six commands, it seemed like an overkill to me.
Checking prefixes of different lengths: Of course, I could just check prefixes of different length of the command string, but that seems to involve lots of boilerplate code.
List representation of strings: I know that I could just transform each
Stringinto achar listand then do something likelet evalcommand command = match String.to_list with | ['#';'e';'x';'i';'t'] -> () (* cumbersome for many commands *) | '#'::'c'::'m'::'d'::'2'::args -> consume_args args (* cumbersome *) | (* and so on *)Mikmatch: I also had a look at Mikmatch, but I'd prefer doing it with OCaml's intrinsic features if possible.
Hashtable approach: Of course I can use a hashtable that maps
Strings toString list -> unit(i.e. functions taking a certain amount of strings as argument, returning()).
So here's the final question: Is there any elegant way that solves this poblem in a straightforward, easily maintainable way (preferrably with little amount of code)?
Camlp4.Struct.Grammarmodule. Or through Lex/Yacc. - nlucaroni