0

In semantic analysis one of the most popular method or data structure used is Hash Table. Implementing hash table is relatively easy however reading this peresentation made it complex for me - I don't know if Im right. Based from the presentation, how do you implement a symbol table with a token (key) that has multiple values?

My idea is to create a table below:

Given input string:
VAR abc, b, c AS INT

   | symbol | datatype | value |
   -----------------------------
   | VAR    | keyword  | null  |
   | abc    | INT      | null  |
   | b      | INT      | null  |
   | c      | INT      | null  |
   | AS     | keyword  | null  |
   | CHAR   | keyword  | null  |

VAR x, w_23=’w’ AS CHAR

   | symbol | datatype | value |
   -----------------------------
   | VAR    | keyword  | null  |
   | x      | CHAR     | null  |
   | w_23   | CHAR     | 'w'   |
   | AS     | keyword  | null  |
   | CHAR   | keyword  | null  |

So, lets say I have a variable aif I lookup (a) then it should be error because looking at the table key a doesn't exist. Also, if w_23=10 should also be an error because w_23 is of type CHAR generally it's just a type checking.

My question is, is it possible to create a symbol table like that of above?, if so how do I implement a symbol table with symbol as key and datatype & value as values?.

Xavier Johanis
  • 59
  • 2
  • 12
  • 1
    You group `datatype & value` into one class, say `SymbolDefinition` and them make a table that maps `String` to `SymbolDefinition`. – Henry Feb 13 '18 at 12:00

2 Answers2

1

You can implement it something like this:

  public class SymbolEntry {
      private String symbol;
      private DataType datatype;
      private Value value;
      ...
  }

where DataType and Value are custom classes that represent the types and values as appropriate. Then the symbol table is simply this:

  HashMap<String, SymbolEntry> symtab = new HashMap<>();

where the String key is the symbol.

In short, you need a custom class to represent the values that comprise a symbol table entry. The rest is left as "an exercise for the reader".

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Sure thing. Just my two cents: I think that `symbol`, in the OP's idea, is the key of the hashtable, so the class `SymbolEntry` should have only the fields `datatype` and `value`. Or at least that's what I understood... – kekolab Feb 13 '18 at 12:08
  • @Gianluca yes, `symbol` is the key while `datatype` and `value` are values – Xavier Johanis Feb 13 '18 at 12:15
  • @Stephen C, do I have to add `put` or `lookup` in `SymbolEntry` class or create the class as is? – Xavier Johanis Feb 17 '18 at 07:32
  • Those are not operations of a symbol table entry. They are operations on a symbol table. The symbol table is the `HashMap`. – Stephen C Feb 17 '18 at 07:41
  • I see, whats inside the `DataType` and `Value` class? – Xavier Johanis Feb 17 '18 at 07:51
  • They are classes that you need to write that will represent the types and values in your language; i.e. the stuff in the `datatype` and `value` columns in your "table". – Stephen C Feb 17 '18 at 07:56
1

I would use an approach based on the Generics.

First you define a generic class like this:

public abstract class GenericEntry<T> {
    protected T value;

    @SuppressWarnings("unchecked")
    public Class<? extends T> getDatatype() {
        return (Class<? extends T>) value.getClass();
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

and then you define a material classes. One for the character, for example:

public class CharacterEntry extends GenericEntry<Character> { }

and another one for integers:

public class IntegerEntry extends GenericEntry<Integer> { }

and a main with some tests:

public class Main {
    public static void main(String[] args) {
        HashMap<String, GenericEntry<?>> myMap = new HashMap<>();

        CharacterEntry characterEntry = new CharacterEntry();
        characterEntry.setValue('c');
        myMap.put("key1", characterEntry);

        IntegerEntry integerEntry = new IntegerEntry();
        integerEntry.setValue(3);
        myMap.put("key2", integerEntry);

        GenericEntry<?> entry1 = myMap.get("key1");
        System.out.println(entry1.getDatatype());
        System.out.println(entry1.getValue());

        GenericEntry<?> entry2 = myMap.get("key2");
        System.out.println(entry2.getDatatype());   
        System.out.println(entry2.getValue());
    }
}

whose output is:

class java.lang.Character
c
class java.lang.Integer
3

as you can see from @stephen-c's answer, the approaches may be differents, but in any case you have to define a class that containts the datatype and the value.

kekolab
  • 801
  • 10
  • 24
  • but value are not constant as it may change during entire run of the program. Example `VAR a=10 AS INT`...`a=2` – Xavier Johanis Feb 13 '18 at 12:27
  • I don't quite understand what you mean when you say that the value is not constant during the run of the program. Does it mean that you associate a new object with a different datatype to the same key? Or does it mean that the same object associated with a key in a point must hold a, let's say, character and later in the flow it must hold a, let's say, integer? – kekolab Feb 13 '18 at 12:31
  • I wouldn't use generics for the symbol table entries. IMO, too heavy-weight, and it doesn't actually give you any benefit. For a start, your symbol table has to contain entries for symbols of all types ... not just primitive types. And the code that uses the entries still has to discriminate (runtime type check) the entries retrieved from the map. – Stephen C Feb 14 '18 at 04:34