0

Current assignment needs me to write a program to read a file with instructions in a very tiny and basic programming language (behaves a little like FORTRAN) and execute those instructions. Basically it's a simple interpreter for the language I guess. It's completely linear, with statements all being defined in sequence and it only has String and integer variables. There are 8 keywords and 4 arithmetic operators I would need to find and define if they exist within the source file, and each line must start off with one of the reserved words. A program in this language might look something like this:

#COMMENTS
LET.... (declares variables with values)
INTEGER myINT
STRING myString
CALCULATE...
PRINT
PRINTLN
END

Can I use a switch block instead of if-loops to find and then execute all these? My concern is that switches don't work with Strings in Java 6, which is what I'm supposed to be using, but I don't see how to easily assign various int values so the switch block would work. Thanks in advance for any suggestions and advice!

Luinithil
  • 63
  • 2
  • 4
  • 10
  • 1
    I think you've answered your own question... – Oliver Charlesworth Jan 07 '12 at 19:06
  • please show some source code... what have your tried ? – Yahia Jan 07 '12 at 19:06
  • 1
    Normally input would be tokenized; token identifiers or enums could be used in a switch statement. That said, there's no need--implement token handlers as an interface impl and dump them into a token handler map. – Dave Newton Jan 07 '12 at 19:20
  • @DaveNewton so to implement token handlers as interface implementation and dump into a token handler map-- would you kindly elaborate on that? I'm very new to Java and often get lost doing basic stuff. :( Should I create a protected class to handle the tokens? – Luinithil Jan 07 '12 at 19:37
  • +1 to what Dave writes, I think implementing each handler as a separate class is much more readable (see my answer below for details) – Seramme Jan 07 '12 at 23:19

2 Answers2

1

If you are talking about converting strings to integers then you could do it with an Java enumerated type:

private enum ReservedWord {
   LET,
   ...
}

// skip blank lines and comments
String[] tokens = codeLine.split(" ");
ReservedWord keyword;
try {
   keyword = ReservedWord.valueOf(tokens[0]);
} catch (IllegalArgumentException e) {
   // spit out nice syntax error message
}

You could also put the processing of the line inside of the enum as a method if you'd like. You could also do it with a Map:

private final Map<String, Integer> reservedWords = new HashMap<String, Integer>();
private final int RESERVED_WORD_LET 1
...
{
   reservedWords.put("LET", RESERVED_WORD_LET);
   ...
}

// skip blank lines and comments
String[] tokens = codeLine.split(" ");
Integer value = reservedWords.get(tokens[0]);
if (value == null) // handle error... ;
switch (value) {
   case 1:
       // LET
       ...
}
Gray
  • 115,027
  • 24
  • 293
  • 354
1

If your language is so simple that every statement begins in its own line and is identified by one word only, then (as Gray pointed out in another comment) you can split the words in each line, then compare the first word against a map. However, I would suggest, instead of mapping the words to ints and then doing one big switch, to map them into objects instead, like this (suggested by Dave Newton):

interface Directive {
    public void execute(String line);
}

class LetDirective implements Directive {
    public void execute(String line) { ...handle LET directive here... }
}

...define other directives in the same way...

Then define the map:

private Map<String, Directive> directives = new HashMap<String, Directive>();
directives.put("LET", new LetDirective());
...

Then in your parsing method:

int firstSpace = line.indexOf(' ');
String command = line;
if (firstSpace > 0)
    command = line.substring(0, firstSpace);
Directive directive = directives.get(command.toUpperCase());
if (directive != null)
    directive.execute(line);
else
    ...show some error...

Each directive would have to parse the rest of the line on its own and handle it correctly inside its execute() method.

The benefit of this over a switch is that you can handle a larger amount of commands without ending up with one gigantic method, but instead with one smaller method per each command.

Seramme
  • 1,340
  • 7
  • 9