我有9种不同的语法。其中一个将被加载,具体取决于它正在解析的文件的第一行txt。
我正在考虑将词法分析器/解析器派生到sep中。类,然后在我得到匹配时立即实例化它们 - 不确定这是否会减慢我的速度但不会。我想一些基准测试是有序的。
真的,速度绝对是我的目标,但我知道这是丑陋的代码。
现在代码看起来像这样:
sin.mark(0)
site = findsite(txt)
sin.reset()
if ( site == "site1") {
loadlexer1;
loadparser1;
} else if (site == "site2") {
loadlexer2;
loadparser2;
}
.................
} else if (site == "site8") {
loadparser8;
loadparser8;
}
findsite(txt) {
...................
if line.indexOf("site1-identifier") {
site = site1;
} else if(line.indexOf("site2-identifier") {
site = site2;
} else if(line.indexOf("site3-identifier") {
site = site3;
}
.........................
} else if(line.indexOf("site8-identifier") {
site = site8;
}
}
一些澄清
1)是的,我确实有9个不同的语法,我用antlr构建,所以他们都有自己的词法分析器/解析器objs。
2)是的,截至目前我们正在比较字符串并且显然将用某种整数映射替换。 我也考虑过将网站标识符固定在一个正则表达式中,但是我不认为这会加快任何速度。
3)是的,这是伪代码所以我不会对这里的语义过于挑剔..
4)kdgregory注意到我无法创建lexer / parser对的一个实例是正确的
我喜欢哈希的想法,让代码看起来更好看,但我不认为它会加速我。
答案 0 :(得分:7)
标准方法是使用Map将关键字符串连接到将处理它们的词法分析器:
Map<String,Lexer> lexerMap = new HashMap<String,Lexer>();
lexerMap.put("source1", new Lexer01());
lexerMap.put("source2", new Lexer02());
// and so on
一旦你检索到标识要使用的词法分析器的字符串,就可以从地图中检索它,如下所示:
String grammarId = // read it from a file, whatever
Lexer myLexer = lexerMap.get(grammarId);
但是,您的示例代码有一些怪癖。首先,indexOf()调用表明您没有独立字符串,并且Map不会查看字符串内部。所以你需要有一些方法从你读过的任何字符串中提取实际的密钥。
其次,词法分析器和解析器通常保持状态,因此您将无法创建单个实例并重用它。这表明您需要创建一个工厂类,并将其存储在地图中(这是抽象工厂模式)。
如果你期望有很多不同的词法分析器/解析器,那么使用地图驱动的方法是有意义的。对于一个小数字,if-else链可能是你最好的选择,正确封装(这是工厂方法模式)。
答案 1 :(得分:2)
使用多态几乎可以保证比字符串操作更快,并且将在编译时检查其是否正确。 site
真的是一个字符串吗?如果是这样,FindSite应该被称为GetSiteName。我希望FindSite返回一个知道相应词法分析器和解析器的Site
对象。
另一个速度问题是编码速度。在单个类中使用不同的词法分析器和解析器肯定会更好(可能在另一个类中具有共享功能)。这会让你的代码变得更小,并且人们更容易理解。
答案 2 :(得分:1)
类似的东西:
Map<String,LexerParserTuple> lptmap = new HashMap<String,LexerParserTuple>(); lpt=lptmap.get(site) lpt.loadlexer() lpt.loadparser()
结合一些正则表达式魔术而不是string.indexOf()来抓取网站的名称应该大大清理你的代码。
答案 3 :(得分:1)
Replace Conditional With Polymorphism
对于findite()的半个小节,你可以简单地设置一个HashMap来从站点标识符到站点。另一种清理方法就是返回站点字符串,因此:
String findsite(txt) {
...................
if line.indexOf("site1-identifier")
return site1;
if(line.indexOf("site2-identifier")
return site2;
if(line.indexOf("site3-identifier")
return site3;
...
}
以这种方式使用indexOf()并不具有表现力;我会使用equals()或contains()。
答案 4 :(得分:1)
我正在考虑将词法分析器/解析器派生到sep中。类,然后在我得到匹配后立即实例化
看起来你已经有了答案。这将创建更灵活的代码,但不是更快。
我想一些基准测试是按顺序
是的,用两种方法衡量并做出明智的决定。我猜你的方式已经足够了。
也许,如果您遇到困难的是"kilometric"方法,可以使用extract method在不同的函数中重构它。
最重要的是首先要有一个能够完成工作的解决方案,即使它很慢,一旦你有了工作,就可以对其进行分析并检测可以提高性能的点。请记住"Rules of optimization"
答案 5 :(得分:1)
假设您的代码效率低下。
实际解析输入需要花费更多时间(例如)1%的时间吗?
如果没有,你就会有更大的“炸鱼”。
答案 6 :(得分:0)
我会更改findsite的类型以返回网站类型(超类),然后利用多态... 这应该比字符串操作更快......
你需要单独的词法分析器吗?
答案 7 :(得分:0)
使用Map将站点配置为loadstrategy结构。然后根据“站点”进行简单查找,然后执行适当的策略。对于findSite()也可以这样做。
答案 8 :(得分:0)
可以有一个标识符与网站的地图,然后迭代地图条目。
// define this as a static somewhere ... build from a properties file
Map<String,String> m = new HashMap<String,String>(){{
put("site1-identifier","site2");
put("site2-identifier","site2");
}}
// in your method
for(Map.Entry<String,String> entry : m.entries()){
if( line.contains(entry.getKey())){
return line.getValue();
}
}
清洁工:是的
更快:不知道......应该足够快
答案 9 :(得分:0)
你可以使用反射
char site = line.charAt(4);
Method lexerMethod = this.getClass().getMethod( "loadLexer" + site, *parameters types here*)
Method parserMethod = this.getClass().getMethod( "loadparser" + site, *parameters types here*)
lexerMethod.invoke(this, *parameters here*);
parserMethod.invoke(this, *parameters here*);
答案 10 :(得分:0)
我不知道Java,但是某些语言允许切换到字符串。
switch(site)
{
case "site1": loadlexer1; loadparser1; break;
case "site2": loadlexer2; loadparser2; break;
...
}
对于秒位,使用正则表达式提取标识符并打开它。您可能最好使用enum
。