当格式包含循环时,特殊格式的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>)