This week's giveaway is in the Android forum.
We're giving away four copies of Android Security Essentials Live Lessons and have Godfrey Nolan on-line!
See this thread for details.
The moose likes Beginning Java and the fly likes HashMap implementation for an interpreter: cannot find symbol error Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "HashMap implementation for an interpreter: cannot find symbol error" Watch "HashMap implementation for an interpreter: cannot find symbol error" New topic
Author

HashMap implementation for an interpreter: cannot find symbol error

Noam Ingalls
Ranch Hand

Joined: Jan 11, 2012
Posts: 60

I'm currently working on an assignment that requires me to write a simple interpreter for a language, with 8 reserve words and the arithmetic operators. So to do that I made up 8 classes (one each for the reserved words) and mapped them all into a HashMap-- the idea is that I can get a substring of the strings in my ArrayList, which will be my reserved word (the reserved word always starts a line of code in the language). The hashmap will then guide the flow over to one of the classes and the rest of the stuff gets done there.

So I was trying to test one of my classes, and for some reason I keep getting hit with the "Cannot find symbol" error on line 56-- symbol: method get(String). The issue seems to be with the get() function in .

This is the for loop the problem line is in:




Also showing the interface my HashMap implements, as well as the class it's supposed to map to.




Thanks in advance for the help!


"How do you define fool?"
"I don't attempt it. I wait for demonstrations. They inevitably surpass my imagination."
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

You've declared directiveHash as a Directive, but the Directive interface does not define a get(String) method.

Which is exactly what the error message is telling you.
Noam Ingalls
Ranch Hand

Joined: Jan 11, 2012
Posts: 60

So I'd need to declare a get(String) method somehow? How do I go about it? (~ 2 months of programming classes at a furious pace, and I'm about to drown in a sea of incomprehension).
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Nemo Inconnu wrote:So I'd need to declare a get(String) method somehow? How do I go about it? (~ 2 months of programming classes at a furious pace, and I'm about to drown in a sea of incomprehension).


It's not clear to me what you're having trouble with. Clearly you understand how to define and implement methods.

You mention HashMap, but then you try to call get(), a Map method, on your Directive reference. Sorry, I'm just not sure what you're trying to accomplish or what specific difficulty you're having.
Noam Ingalls
Ranch Hand

Joined: Jan 11, 2012
Posts: 60

Basically my entire idea for the whole project was -- Get the source text file read into an ArrayList<String>, tokenize the string to get the first word in the string (which would be the command), and then based on that, use the HashMap to get the information to the right class for parsing the rest of the string and processing it accordingly. I set up the Directive interface that way, but didn't realise that I'd need to have get() defined in it as well. So now I'm not really sure how I'm supposed to add the get() method to my interface.

Would this be right? Or at least is it supposed to be something like this?

Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Nemo Inconnu wrote:Basically my entire idea for the whole project was -- Get the source text file read into an ArrayList<String>, tokenize the string to get the first word in the string (which would be the command), and then based on that, use the HashMap to get the information to the right class for parsing the rest of the string and processing it accordingly.


Okay, so that sounds like you want Map<String, X>, where the String (the key) will be the "command", and X (the value) will be some class or interface that has a method like parse() or execute() that processes that String.

Does that sound right? And if so, is your Directive interface the X--the thing that processes the string?

I set up the Directive interface that way, but didn't realise that I'd need to have get() defined in it as well.


If it's as I describe above, then, no you don't need get() in Directive. But you also shouldn't be calling Directive.get(). You should be calling Map.get().

So if I described your situation correctly, you'd have something like this:

Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

I suspect your problem is here:



Don't use the same variable name for two different things.
Noam Ingalls
Ranch Hand

Joined: Jan 11, 2012
Posts: 60

Yep, that's the situation exactly! Gotta question though: why would we need
void execute(String args);
in the Directive interface?


Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Nemo Inconnu wrote:Yep, that's the situation exactly! Gotta question though: why would we need
void execute(String args);
in the Directive interface?




Well, you're the one that put it there in the first place, so why did you?

Or, from the other direction, how would you call execute() if you didn't define it in the first place?
Noam Ingalls
Ranch Hand

Joined: Jan 11, 2012
Posts: 60

Eh, no, I was wondering why the method declaration had to be void, not why the need to call execute(). Sorry for being obscure, I've been up nearly 4 nights running on limited sleep trying to get this done and making limited progress.

Also, could you kindly explain this bit? I got my current HashMap implementation from some forum when I asked if there was a better way to do the commands than a giant switch block, and there wasn't much explanation offered as to the whys and hows. So I'm kinda lost on how to use HashMaps like this, since we never covered them in class-- everything I know is mostly monkey-see-monkey-do and reading up on documentation.

String fullCommandWithArgs = "cmd1 arg1 arg2";

// ... code to split out command and args ...
String commandOnly = ...;
String args = ...;

Directive d = commandMap.get(commandOnly);
d.execute(args);



Also, is there a better way than String.split() or StringTokenizer? I need a 2-step implementation to get the commands right: step one being parsing code to command+ instructions, then step 2 needs me to parse the various tokens in different ways, which has me stumped.
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Nemo Inconnu wrote:Eh, no, I was wondering why the method declaration had to be void


It doesn't have to be. Again, you made that choice. It's in your original post. If you want it to return something, declare an appropriate return type. If it doesn't need to return anything, declare it void.

Also, could you kindly explain this bit? I got my current HashMap implementation from some forum when I asked if there was a better way to do the commands than a giant switch block, and there wasn't much explanation offered as to the whys and hows. So I'm kinda lost on how to use HashMaps like this, since we never covered them in class-- everything I know is mostly monkey-see-monkey-do and reading up on documentation.



Well, a Map is just a way to associate a value with a key. It's basically a simple lookup facility. So, in this case, given the key that is the command, you look up an object that knows how to process that command. It's not necessarily better or worse than a switch. They're just two different approaches.

The advantage of a switch is that you don't have to build an explicit data structure to hold your lookups--you're using a language feature to do it directly, so it's slightly simpler. In theory, it will also be faster to find the appropriate Directive with a switch, but, unless the execute() method is very, very tiny, that difference will almost always be totally insignificant.

The advantages of the Map are 1) You can build up your mappings at runtime; you don't need to recompile to change, add, or remove mappings, and 2) Up until Java 7, you couldn't switch on a String, although the introduction of enums in 1.5 makes this largely a non-issue.


Also, is there a better way than String.split() or StringTokenizer? I need a 2-step implementation to get the commands right: step one being parsing code to command+ instructions, then step 2 needs me to parse the various tokens in different ways, which has me stumped.


As with most questions asking what is "better", the answer to this one is, "it depends." If the format is always command arg1 ... argN, then I would go with String.split(). One call to String.split() will separate command from args, and another call will give you individual args. If args allows quoting so that multiple words can count as one arg, it gets trickier, and you might want a getopts library or something.

If it's more complex than that, then you'll probably want something more sophisticated, like a parser builder library. For instance, if you're thinking of something like Java, and considering "if" as a "command", and then other stuff as its args, you're absolutely barking up the wrong tree.
Noam Ingalls
Ranch Hand

Joined: Jan 11, 2012
Posts: 60

Hmm, no, the language is totally linear in implementation. The format is indeed always command arg1...argN, but I DO need args where multiple words count as one arg in at least one case though; it's that pesky LET command, in particular when dealing with String variables, since default tokenizing goes by whitespaces:


Given that, how would you suggest I go about tokenizing the string? If I were using String.split() I'd make my first call split the string once, but then I'm not too sure what next, since String.split() splits the String into an array of Strings, and that might be kinda tricky to work with... correct me if I'm wrong but calling String.split() in the first step, e.g. creates an array of Strings, made from all the Strings parsed from the source file, and not just the single line of code being worked on yes?
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Nemo Inconnu wrote:Hmm, no, the language is totally linear in implementation. The format is indeed always command arg1...argN, but I DO need args where multiple words count as one arg in at least one case though; it's that pesky LET command, in particular when dealing with String variables, since default tokenizing goes by whitespaces:


Given that, how would you suggest I go about tokenizing the string?


I'd still use split to separate the LET command out from its args. As for the rest I'd look for a 3rd party library that would do it for me, and if I weren't allowed to do that or couldn't find one, and if quotes were the only special case I had to worry about, I'd probably write a simple state machine and process the args portion char-by-char.
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Nemo Inconnu wrote:correct me if I'm wrong but calling String.split() in the first step, e.g. creates an array of Strings, made from all the Strings parsed from the source file, and not just the single line of code being worked on yes?


Eh? split() doesn't know anything about your file. It does exactly what the docs say it does--splits up the "this" String as per the regex passed in to that call. If your String is the whole file's contents (bad idea), it operates on that (with possible gotchas based on the dotall and multiline settings), and if you call it on a single line (better approach, assuming you have one command per line), then that's what it operates on.
Noam Ingalls
Ranch Hand

Joined: Jan 11, 2012
Posts: 60

Looks like I need to go fix that loop then; I'm getting my entire file split up according to the regex line by line, when it'd be easier for it to read one line, process, and then go to the next line. Now to figure out how that's supposed to happen code-wise.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7549
    
  18

Nemo Inconnu wrote:Hmm, no, the language is totally linear in implementation. The format is indeed always command arg1...argN, but I DO need args where multiple words count as one arg in at least one case though; it's that pesky LET command, in particular when dealing with String variables, since default tokenizing goes by whitespaces:

Well, one possibility would be to first parse for quoted strings and change all spaces inside them to some unlikely character or escape sequence; then change them back afterwards.

The only problem with that is that you'll probably need to come up with a notation for all possible whitespace characters (I believe '%nnn' is used quite often, where nnn is the octal value of the character; but that requires you to also substitute '%'s).

Don't forget that you may also have to deal with strings containing quotes, and strings containing strings.

Sounds like you have a task ahead of you.

Winston


Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Nemo Inconnu wrote:Looks like I need to go fix that loop then; I'm getting my entire file split up according to the regex line by line, when it'd be easier for it to read one line, process, and then go to the next line. Now to figure out how that's supposed to happen code-wise.


BufferedReader has a readLine() method.
Noam Ingalls
Ranch Hand

Joined: Jan 11, 2012
Posts: 60

Does that mean that I need to parse the line BEFORE it reaches the ArrayList for storage? Currently the source code data is stored in an ArrayList before parsing.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7549
    
  18

Noam Ingalls wrote:Does that mean that I need to parse the line BEFORE it reaches the ArrayList for storage? Currently the source code data is stored in an ArrayList before parsing.

I don't think so, but you do need to do it before you do your split, since the whole reason for it is to make sure that quoted strings end up as single tokens.

BTW, it's only one possibility - as is the "tokenizing" - but I think it's a fairly standard approach for an interpreter.

My worry is that you seem to have assumed that your "statements" are always going to be on one line. How do you plan to deal with violations?

Winston
Noam Ingalls
Ranch Hand

Joined: Jan 11, 2012
Posts: 60

My worry is that you seem to have assumed that your "statements" are always going to be on one line. How do you plan to deal with violations?


Ack, good point. Well having statements on more than one line is a violation of the language's syntax, so I guess Syntax error message and then exit the program when it hits that point? So what coud I use to parse the line before the split? It's all one line before hand after all. Gods, been working on this for 2 weeks and about to throw laptops in frustration. And here 2 months ago I was eager to start off programming in my Masters course (I've never done any computing-related course before, my undergrad was in management and psych).
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7549
    
  18

Noam Ingalls wrote:So what coud I use to parse the line before the split? It's all one line before hand after all.

No, it's all one file (or Stream), and it's highly likely that that file is going to be arranged in lines, because that's generally how people work.

One possibility would be to require a statement terminator (like the ';' in Java). Then, any line whose last character isn't a terminator is a violation. Allowing only one statement per line would probably make things simpler too.

Gods, been working on this for 2 weeks and about to throw laptops in frustration. And here 2 months ago I was eager to start off programming in my Masters course...

Welcome to programming. Anyone who hasn't got scars on their forehead isn't a real programmer.

It sounds to me like your flailing around a bit. My advice would be to switch off the computer and sit down with a notebook and paper and gather your thoughts.

  • What is this "language" supposed to do? I'm presuming that it's a proof-of-concept, not a fully-blown language (in two weeks? Try two years).
  • List the commands that you want to support.
  • Is the language going to be typed? If so, what types will you allow? (Hint: you can do quite a lot with just numbers, strings and an array type)
  • List the classes that are going to make up the language (eg, Statement, Variable, Constant, Literal and probably many others).

  • Also list the other rules that the language imposes, for example:
  • The characters it allows - for example, it may be easiest to stick to standard ASCII.
  • Statement terminators (if any).
  • Quoted strings, including specifically:
    1. How you handle embedded quoted strings (simplest may be to require double quotes outside and single quotes inside).
    2. How you handle a string with a quote in it.
    3. Any other special characters that a quoted string might have to support (eg, a newline).
  • How you plan to handle blocks and/or loops.
  • Are you going to allow methods? If so, how do you handle return values?

  • and there's probably tons of stuff I've missed, but you need to have a plan for all of it; otherwise you'll just be doing what I call "existential programming".

    Jean-Paul Sartre may have been a fine philosopher, but he'd make a lousy programmer.

    Winston

    PS: In addition to requiring that your 'command' be the first token in a statement, you might also want to come up with a naming convention for variables. 'bash'-style scripts, for example, require that they're prefixed with a '$' sign.
    Noam Ingalls
    Ranch Hand

    Joined: Jan 11, 2012
    Posts: 60

    Aye it's a proof of concept-- my lecturer's proof of concept since he's the one who came up with it. It's fairly simple, and its rules are pretty much like BASIC. I doubt he'd take too much off if I don't manage to support quoted or embedded strings; not that I can afford to lose any more marks than I already have given that I'm rather overdue on this project and my marks are draining down the toilet with each day. There isn't any need for loops or blocks either-- unless I decide to be heroic and come up with that on my own. I'll settle for getting the basic 8 reserved keywords and associated functionality down and working. IF I ever do manage that bit even. Just need to be able to declare two types of variables: Strings and ints, be able to have a LET statement taht will associate a previously declared variable with a value and do calculations in it and print things to the console. Unfortunately right now I'm all as to what the heck I'm even doing.
     
    It is sorta covered in the JavaRanch Style Guide.
     
    subject: HashMap implementation for an interpreter: cannot find symbol error
     
    Similar Threads
    MultiDimenaional Array sort
    Project Euler #17
    Command pattern
    iterate problem in struts2