所以,我刚开始学习antlr4,我只是编写了一种非常简单的编程语言。该语言可以创建变量(int,booleans和strings),更改其值并输出其值。但是,我试图做一个if语句,但经过多次尝试,它没有用。谷歌搜索也没有帮助,因为大多数其他代码太过不同,无法理解并自行应用它。我的大多数代码都遵循本教程:
https://progur.com/2016/09/how-to-create-language-using-antlr4.html
这是我的语法文件
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';
最后这里是听众类
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();
}
}
}
我想要实现的if语句的语法是:
begin
if 5 MORETHAN 4 then
.....
ENDIF
end
我是antlr4的新手,其中一些概念对我来说很新,如果有人能帮助我,那就太好了谢谢!
答案 0 :(得分:0)
ifState
规则中未提及 statement
。
此外,请记住,您已定义应该有“STARTIF&#39;在THEN
之后 - 它不在您的示例输入中。
另一个观察结果是,您的statement
规则以|;
结尾 - 这意味着它允许空语句。在没有语句分隔符的语言中,这没有意义。
正如@CoronA所指出的那样,问题是您首先在主电话中调用program
规则,然后拨打ifState
。这样做意味着您希望首先解析程序(从begin
开始,以end
结尾),然后 ,指示解析器解析if语句。因此,当前代码将解析的输入必须类似于:
begin
...
end
if 5 MORETHAN 4 then
STARTIF
...
ENDIF
您可能想要做的只是让ifState
只是另一种可能的语句类型,即将其添加到statement
规则并仅从main调用program
。