mercredi 25 avril 2018

How to create and parse if statements in Antlr 4

So, I just started learning antlr4 and I just made an extremely simple programming language. The language can create variables (int, booleans, and strings), change their values, and output their values. However, I am trying to do an if statement but after many tries, it didn't work. Googling didn't help either since most of the others code is too different to understand and apply it on my own. Most of my code follow this tutorial:

https://progur.com/2016/09/how-to-create-language-using-antlr4.html

Here's my grammar file

grammar valhallap;

program : 'begin' statement+ 'end';

ifState : ifDec 'STARTIF' statement+ 'ENDIF';



statement :  createINT|assign|addINT|printVar|createString|print|createBool|;




ifDec: 'if' (NUMBER|ID) EXPRESION (NUMBER|ID) 'then';
createINT : 'new' 'int' ID;
createBool: 'new' 'bool' ID;
createString : 'new' 'string' ID;
addINT : 'addINT' ID NUMBER;
assign : 'set' ID (STRING|BOOL|NUMBER);
print : 'output' 'say' STRING;
printVar : 'output' 'var' ID;





ID : [A-z]+;
NUMBER : [0-9]+ ;
STRING : ["] ( ~["\r\n\\] | '\\' ~[\r\n] )* ["] | ['] ( ~['\r\n\\] | '\\' ~[\r\n] )* ['];
BOOL : 'true' | 'false';
WS : [ \n\t]+ -> skip;
Comment: '**' ~( '\r' | '\n' )* -> skip;
STATEMENT : .;
EXPRESION:
     'MORETHAN'
     |'LESSTHAN'
     |'EQUALS'
     |'LESSEQUALS'
     |'MOREEQUALS';

Finally here's the listener class

import com.power.valhallap.grammar.*;
import java.io.FileInputStream;
import java.io.IOException;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;

/**
 *
 * @author admin
 */

public class ValhallaListener extends valhallapBaseListener{

/**
 * @param args the command line arguments
 */
private Map<String, Object> variables;
public static boolean ifState = false;

public ValhallaListener()
{
    //init all the variables
    variables = new HashMap<>();
}


//if statements



@Override
public void exitAssign(valhallapParser.AssignContext ctx)
{
    String variable = ctx.ID().getText();


    if(variables.get(variable) instanceof String)
    {
        if(ctx.NUMBER() != null || ctx.BOOL() != null)
        {`enter code here`
            System.out.println("error expecting string");
        }
    }
    if(variables.get(variable) instanceof Boolean)
    {
        if(ctx.NUMBER() != null || ctx.STRING() != null)
        {
            System.out.println("error expecting boolean");
        }
    }
    if(variables.get(variable) instanceof Integer)
    {
        if(ctx.STRING() != null || ctx.BOOL() != null)
        {
            System.out.println("error expecting integer");
        }
    }

    if(ctx.STRING() != null)
    {
        if(variables.get(variable) instanceof String)
        {
           String finalString = ctx.STRING().getText();
           finalString = finalString.replace("\"", "");
           variables.put(variable, finalString);
        }

    }

    if(ctx.NUMBER() != null)
    {
        if(variables.get(variable) instanceof Integer)
        {
           variables.put(variable, Integer.parseInt(ctx.NUMBER().getText()));
        }

    }

    if(ctx.BOOL() != null)
    {
        if(variables.get(variable) instanceof Boolean)
        {
           boolean answer = Boolean.parseBoolean(ctx.BOOL().getText());

           variables.put(variable, answer);
        }

    }


}

@Override
public void exitCreateINT(valhallapParser.CreateINTContext ctx)
{
    //get's the variable name of int
    String variableName = ctx.ID().getText();

     if(!variables.containsKey(variableName))
    {
        //add the name to the hashmap with the init value of 0
        variables.put(variableName, 0);
    }
}



@Override
public void exitAddINT(valhallapParser.AddINTContext ctx)
{
    //get the var name
    String varName = ctx.ID().getText();

    //get the value
    int first = Integer.parseInt(variables.get(varName).toString());

    int addValue = Integer.parseInt(ctx.NUMBER().getText());

    int finalValue = first + addValue;

    //assign the new value

    variables.put(varName, finalValue);
}


 @Override
public void exitPrintVar(valhallapParser.PrintVarContext ctx)
{
    String varName = ctx.ID().getText();



    System.out.println(variables.get(varName));
}

@Override
public void exitPrint(valhallapParser.PrintContext ctx)
{
    String output = ctx.STRING().getText();
    output = output.replace("\"", "");
    System.out.println(output);
}

@Override
public void exitCreateString(valhallapParser.CreateStringContext ctx)
{
    String variableName = ctx.ID().getText();


    if(!variables.containsKey(variableName))
    {
        //add the name to the hashmap with the init value of null
        variables.put(variableName, "");
    }
}



@Override
public void exitCreateBool(valhallapParser.CreateBoolContext ctx)
{
    //get's the variable name of int
    String variableName = ctx.ID().getText();

     if(!variables.containsKey(variableName))
    {
        //add the name to the hashmap with the init value of false
        variables.put(variableName, false);
    }
}





public static void main(String[] args) {
   try {
    ANTLRInputStream input = new ANTLRInputStream(
        new FileInputStream(args[0]));    

    valhallapLexer lexer = new  valhallapLexer(input);
    valhallapParser parser = new valhallapParser(new CommonTokenStream(lexer));
    parser.addParseListener(new ValhallaListener());

    // Start parsing
    parser.program();


    if(ifState)
    {
        parser.ifState();
    }



    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

The syntax of the if statement that I want to achieve is:

begin
if 5 MORETHAN 4 then
   .....
ENDIF
end

I new to the antlr4 and some of the concepts are new to me, it would be great if anyone could help me thanks!

Aucun commentaire:

Enregistrer un commentaire