当格式包含循环时,特殊格式的Java检查字符串 介绍

当格式包含循环时,特殊格式的Java检查字符串 介绍,java,string,Java,String,我正在做一个项目,用户可以用特殊的格式输入事实和规则,但我在检查格式是否正确和获取信息方面遇到了一些问题 启动程序时,用户可以在文本区域中输入“命令”,并将该文本发送到parseCommand方法,该方法根据用户编写的内容确定要执行的操作。例如,要添加事实或规则,可以使用前缀+。或者使用-删除事实或规则等 我已经创建了处理前缀的系统,但是事实和规则格式有问题 事实和规则 事实:这些由字母数字名称定义,并包含属性列表(每个属性都带有符号)和真值。属性也由字母数字名称定义,包含2个字符串(称为参数)

我正在做一个项目,用户可以用特殊的格式输入事实和规则,但我在检查格式是否正确和获取信息方面遇到了一些问题

启动程序时,用户可以在文本区域中输入“命令”,并将该文本发送到
parseCommand
方法,该方法根据用户编写的内容确定要执行的操作。例如,要添加事实或规则,可以使用前缀
+
。或者使用
-
删除事实或规则等

我已经创建了处理前缀的系统,但是事实和规则格式有问题

事实和规则 事实:这些由字母数字名称定义,并包含属性列表(每个属性都带有
符号)和真值。属性也由字母数字名称定义,包含2个字符串(称为参数),每个字符串都带有符号。属性也可以是负数,方法是放置
在列表中它的前面。例如,用户可以键入以下内容将这3个事实添加到程序中:

+father(<parent(<John>,<Jake>)>, true)

+father(<parent(<Jammie>,<Jake>)>, false)

+father(!<parent(<Jammie>,<Jake>)>, true)

+familyTree(<parent(<John>,<Jake>)>, <parent(<Jammie>,<Jake>)> , true)

+fathers(<parent(<John>,<Jake>)>, !<parent(<Jammie>,<Jake>)> , true)
规则属性

正常规则告诉我们,如果在下面的示例中,
X
Y
的父项,这意味着
Y
X
的子项:

son(<parent(<X>,<Y>)> => <child(<Y>,<X>)>)
son(<parent(<X>,<Y>)> => <child(<Y>,<X>)>, Negtive)
然而,
Reversive
规则告诉我们,如果在下面的示例中,
Y
X
的子级,这意味着
X
Y
的父级

son(<parent(<X>,<Y>)> => <child(<Y>,<X>)>, Reversive)
这是我用来存储规则的类:

public class Rule implements Serializable{

    private Property derivative;
    private Property impliant;
    private boolean negative;
    private boolean reversive;
    private String name;

    public Rule(Property derivative, Property impliant, boolean negative, boolean reversive) throws InvalidPropertyException{
        if(!this.validRuleProperty(derivative) || !this.validRuleProperty(impliant))
            throw new InvalidPropertyException("One or more properties are invalid");
        this.derivative = derivative;
        this.impliant = impliant;
        this.negative = negative;
        this.reversive = reversive;
    }
    //getters and setters here
}
物业类别:

public class Property implements Serializable{

    private String name;
    private String firstArgument;
    private String secondArgument;

    public Property(String name, String firstArgument, String secondArgument){
        this.name = name;
        this.firstArgument = firstArgument;
        this.secondArgument = secondArgument;
    }
以上示例均为有效输入。以下是一些无效输入示例:

事实:

未为参数提供true或false:

+father(<parent(<John>,<Jake>)>) 
提供的属性无效:

+father(<parent(<John>)>, true) 

+father(<parent(John, Jake)>, true) 

+father(<parent(John, Jake, Michel)>, true) 

+father(parent(<John>,<Jake>), true)

我走对了吗?如果这是一个好的语法文件,我以后如何测试和使用它?

我认为语法分析器不适合解决您的问题。无论如何,通过使用正则表达式和一些字符串实用程序,您可以更简单地处理它

最好从小问题开始,转移到大问题: 首先解析属性本身似乎很容易,因此我们编写了一个方法来实现这一点:

 private static Property toProp(String propStr) {
    String name = propStr.substring(1,propStr.indexOf("("));
    String[] arguments = propStr.substring(propStr.indexOf('(')+1,propStr.indexOf(')')).split(",");
    return new Property(name,
            arguments[0].substring(1,arguments[0].length()-1),
            arguments[1].substring(1,arguments[1].length()-1));
  }
为了解析事实字符串,使用regex使事情更简单,属性的regex是 /借助我们已经编写的toProp方法,我们可以创建另一种方法来解析事实:

public static Fact handleFact(String factStr) {
    Pattern propertyPattern = Pattern.compile("<[\\w\\d]*\\([<>\\w\\d,]*\\)>");
    int s = factStr.indexOf("(") + 1;
    int l = factStr.lastIndexOf(")");
    String name = factStr.substring(0,s-1);
    String params = factStr.substring(s, l);
    Matcher matcher = propertyPattern.matcher(params);
    List<Property> props  = new ArrayList<>();
    while(matcher.find()){
      String propStr = matcher.group();
      props.add(toProp(propStr));
    }
    String[] split = propertyPattern.split(params);
    boolean truth = Boolean.valueOf(split[split.length-1].replaceAll(",","").trim());
    return new Fact(truth,props,name);
  }
publicstaticfacthandlefact(stringfactstr){
模式属性模式=Pattern.compile(“”);
int s=factStr.indexOf(“(”)+1;
int l=factStr.lastIndexOf(“)”;
String name=factStr.substring(0,s-1);
String params=factStr.substring(s,l);
Matcher Matcher=propertyPattern.Matcher(参数);
List props=new ArrayList();
while(matcher.find()){
String propStr=matcher.group();
道具添加(toProp(propStr));
}
String[]split=propertyPattern.split(参数);
布尔真值=boolean.valueOf(split[split.length-1].replaceAll(“,”,“).trim());
返回新事实(真相、道具、名称);
}
解析规则与事实非常相似:

 private static Rule handleRule(String ruleStr) {
    Pattern propertyPattern = Pattern.compile("<[\\w\\d]*\\([<>\\w\\d,]*\\)>");
    String name = ruleStr.substring(0,ruleStr.indexOf('('));
    String params = ruleStr.substring(ruleStr.indexOf('(') + 1, ruleStr.lastIndexOf(')'));
    Matcher matcher = propertyPattern.matcher(params);
    if(!matcher.find())
      throw new IllegalArgumentException();
    Property prop1 = toProp(matcher.group());
    if(!matcher.find())
      throw new IllegalArgumentException();
    Property prop2 = toProp(matcher.group());
    params = params.replaceAll("<[\\w\\d]*\\([<>\\w\\d,]*\\)>","").toLowerCase();
    return new Rule(name,prop1,prop2,params.contains("negative"),params.contains("reversive"));
  }
private静态规则句柄(String-ruleStr){
模式属性模式=Pattern.compile(“”);
String name=ruleStr.substring(0,ruleStr.indexOf('('));
String params=ruleStr.substring(ruleStr.indexOf('(')+1,ruleStr.lastIndexOf(')));
Matcher Matcher=propertyPattern.Matcher(参数);
如果(!matcher.find())
抛出新的IllegalArgumentException();
属性prop1=toProp(matcher.group());
如果(!matcher.find())
抛出新的IllegalArgumentException();
属性prop2=toProp(matcher.group());
params=params.replaceAll(“,”).toLowerCase();
返回新规则(名称、prop1、prop2、params.contains(“负”)、params.contains(“反向”);
}

我恐怕无法从您的描述中理解您试图解析的确切语法,但我知道您正试图从解析的语法创建实体对象。以下几个演示文件演示了如何使用ANTLR-4和Maven进行此操作:

pom.xml:


4.0.0
com.stackoverflow

基本上你有一个非形式语法,你需要构建一个语法分析器。我的建议是,你将语法形式化,并使用像ANTLR或JavaCC这样的工具来构建语法分析器。开始时比较复杂,但最后会更好。你的“特殊格式”看起来像prolog。如果您感到懒惰,您可以简单地调整用户的输入并将其发送到prolog编译器,当prolog程序在不同的进程中运行时,您可以将用户的查询发送到它,并将结果发送回您的程序。或者您可以研究prolog如何工作,也许这会让您了解如何构建您自己的解析器。我建议将问题分解为令牌解析器。让每个解析器解析当前输入,直到无法解析或出现错误。然后从解析器中获取不同的令牌并存储them@smac89这是因为我受prolog的启发做了类似的事情,但是,在我完成了第一部分之后,我想要通过添加更多存储data@lexicore我正在研究它,它看起来很有希望(目前正在查看JavaCC)。请随意使用我的play创建一个开箱即用的语法树(下载源代码)
+father(<parent(<John>)>, true) 

+father(<parent(John, Jake)>, true) 

+father(<parent(John, Jake, Michel)>, true) 

+father(parent(<John>,<Jake>), true)
+son(<parent(<X>,<Y>)> => child(<Y>,<X>))

+son(parent(<X>,<Y>) => child(<Y>,<X>))

+son(<parent(<X>,<Y>)> => <child(<Z>,<X>)>) (Note the Z in the child property)

+son(<parent(<Not Valid>,<Y>)> => child(<Y>,<X>)) (Invalid argument for first property)

+son(=> child(<Y>,<X>))
+familyTree(<parent(<John>,<Jake>)>, <parent(<Jammie>,<Jake>)> , true)
/** Grammer used by communicate parser */

grammar communicate;


/*
 * Parser Rules
 */

argument            : '<' + NAMESTRING + '>' ;

ruleArgument        : '<' + RULESTRING + '>' ;

property            : NAMESTRING + '(' + argument + ',' + argument + ')' ;

propertyArgument    : (NEGATIVITY | POSITIVITY) + property + '>' ;

propertyList        : (propertyArgument + ',')+ ;

fact                : NAMESTRING + '(' + propertyList + ':' + (TRUE | FALSE) + ')';

rule                : NAMESTRING + '(' + ruleArgument + '=>' + ruleArgument + ':' + RULEOPTIONS + ')' ;

/*
 * Lexer Rules
 */

fragment LOWERCASE  : [a-z] ;
fragment UPPERCASE  : [A-Z] ;

NAMESTRING          : (LOWERCASE | UPPERCASE)+ ;

RULESTRING          : (UPPERCASE)+ ;

TRUE                : 'True';

FALSE               : 'False';

POSITIVITY          : '!<';

NEGATIVITY          : '<' ;

NEWLINE             : ('\r'? '\n' | '\r')+ ;

RULEOPTIONS         : ('Negative' | 'Negative' + ',' + 'Reversive' | 'Reversive' );

WHITESPACE          : ' ' -> skip ;
 private static Property toProp(String propStr) {
    String name = propStr.substring(1,propStr.indexOf("("));
    String[] arguments = propStr.substring(propStr.indexOf('(')+1,propStr.indexOf(')')).split(",");
    return new Property(name,
            arguments[0].substring(1,arguments[0].length()-1),
            arguments[1].substring(1,arguments[1].length()-1));
  }
public static Fact handleFact(String factStr) {
    Pattern propertyPattern = Pattern.compile("<[\\w\\d]*\\([<>\\w\\d,]*\\)>");
    int s = factStr.indexOf("(") + 1;
    int l = factStr.lastIndexOf(")");
    String name = factStr.substring(0,s-1);
    String params = factStr.substring(s, l);
    Matcher matcher = propertyPattern.matcher(params);
    List<Property> props  = new ArrayList<>();
    while(matcher.find()){
      String propStr = matcher.group();
      props.add(toProp(propStr));
    }
    String[] split = propertyPattern.split(params);
    boolean truth = Boolean.valueOf(split[split.length-1].replaceAll(",","").trim());
    return new Fact(truth,props,name);
  }
 private static Rule handleRule(String ruleStr) {
    Pattern propertyPattern = Pattern.compile("<[\\w\\d]*\\([<>\\w\\d,]*\\)>");
    String name = ruleStr.substring(0,ruleStr.indexOf('('));
    String params = ruleStr.substring(ruleStr.indexOf('(') + 1, ruleStr.lastIndexOf(')'));
    Matcher matcher = propertyPattern.matcher(params);
    if(!matcher.find())
      throw new IllegalArgumentException();
    Property prop1 = toProp(matcher.group());
    if(!matcher.find())
      throw new IllegalArgumentException();
    Property prop2 = toProp(matcher.group());
    params = params.replaceAll("<[\\w\\d]*\\([<>\\w\\d,]*\\)>","").toLowerCase();
    return new Rule(name,prop1,prop2,params.contains("negative"),params.contains("reversive"));
  }
grammar communicate;

@header {
    package com.stackoverflow.communicate.frontend;
}

fact returns [com.stackoverflow.communicate.ir.Property value]
   : property { $value = $property.value; }
   ;

property returns [com.stackoverflow.communicate.ir.Property value]
   : STRING '(<' argument { com.stackoverflow.communicate.ir.ArgumentTerm lhs = $argument.value; } '>,<' argument '>)' { $value = new com.stackoverflow.communicate.ir.Property($STRING.text, lhs, $argument.value); }
   ;

argument returns [com.stackoverflow.communicate.ir.ArgumentTerm value]
   : STRING { $value = new com.stackoverflow.communicate.ir.ArgumentTerm($STRING.text); }
   ;

STRING
   : [a-zA-Z]+
   ;
parent(<John>,<Jane>)