所以找到了一个很好的语法计算器,并从这里复制了一些lil变化:https: //dexvis.wordpress.com/2012/11/22/a-tale-of-two-grammars/
我有两个文件:Parser和Lexer.看起来像这样:
parser grammar Parser;
options{
language = Java;
tokenVocab = Lexer;
}
// PARSER
program : ((assignment|expression) ';')+;
assignment : ID '=' expression;
expression
: '(' expression ')' # parenExpression
| expression ('*'|'/') expression # multOrDiv
| expression ('+'|'-') expression # addOrSubtract
| 'print' arg (',' arg)* # print
| STRING # string
| ID # identifier
| INT # integer;
arg : ID|STRING;
Run Code Online (Sandbox Code Playgroud)
和Lexer:
lexer grammar WRBLexer;
STRING : '"' (' '..'~')* '"';
ID : …Run Code Online (Sandbox Code Playgroud) 我最近使用相应的gradle版本将我的Android Studio升级到版本2.3.
我的项目中有两个模块,我使用gradle函数导出为jar:
task createJar(type: Copy) {
from('build/intermediates/bundles/release/')
into('libs/')
include('classes.jar')
rename('classes.jar', 'myExample.jar')
}
createJar.dependsOn(deleteJar, build)
Run Code Online (Sandbox Code Playgroud)
但是在升级之后,这不再起作用了.在Android Studio中,我将Build Variant设置为"Release",但在运行我的任务后,我的lib文件夹中将没有JAR.我检查了
build/intermediates/bundles/文件夹,并且没有生成发布文件夹.只有一个default和一个debug文件夹.有没有办法再次从发布版本中获取外部JAR?
最后几天我正在研究我的语法,以便能够计算正常表达式,例如:2+2*5;2^2 或设置变量如 y=5+5;等等。
现在我想解析像 f(a,b)=2*a*b; 这样的函数。然后像 f(5,7) 一样稍后调用它们;我有一些麻烦。
所以假设我尝试解析这样的函数声明:
function:name=Var'(' varNames=(MultVar|Var) ')' '=' (Var|Number) (operator=('*'|'/'|'+'|'-') (Var|Number))* SEMI;
Run Code Online (Sandbox Code Playgroud)
所以这(有点)有效,但我认为它有点“脏”或其他什么。所以我和一个听众一起工作,当我在“exitFunction”中时,我真的不知道如何最好地处理这个函数,所以我可以评估 f(5,7) 之类的东西;好简单。
我有一个名为“Function.java”的 Java 类和方法 "public double eval(double... args)"
所以现在我有属性字符串arguments; String expression; String name;,然后我需要在侦听器中花费大量时间并尝试在字符串中找到正确的参数等。很多 substring() 和 indexOf() 等只是试图找到名称、参数和表达式。然后我将该函数保存在 Hashmap 中。
在我的解析器中,函数调用如下所示:
functioncall: name=Vart '('para=(MultipleNumbers) ')' SEMI;
Run Code Online (Sandbox Code Playgroud)
MultipleNumbers 将是:
MultipleNumber: Number(',' Number)+;
Run Code Online (Sandbox Code Playgroud)
在词法分析器中。然后我尝试从字符串中获取参数,并在函数中替换它们。然后我有一个正常的表达式,我的程序可以再次解决它。
由于这对我来说似乎太难了,而且几乎不可能获得所有正确的“子字符串”等,我认为必须有更好的方法来实现这样的事情。尤其是当我想做以下事情时:
f(a,b)=2*a+b; a=5; f(a,5)
Run Code Online (Sandbox Code Playgroud)
它变得更加困难,因为我无法混合数字和变量。那么有没有一种好方法来实现“功能评估器”。也许我可以在 Hashmap 中保存一整棵树,然后只需更改树内的变量并解析它,或者?认为我的语法对于任务来说也非常糟糕。
由于我过去并没有真正与 antlr 合作,因此我感谢每一个帮助。希望可以有人帮帮我。对不起,我的英语不好,我希望你能理解我。
亲切的问候
FelRPI
我有一个关于泛型的问题。所以假设我有 3 个类“Foo”、“Bar”(它是 Foo 的子类)、一个类“Factory”和一个接口“TestInterface”。我想编写一个通用方法,它只允许“直接”实现接口的对象,所以没有子类。这对我来说很难,因为 Java8 似乎比 Java7“更聪明”。
所以这里有一个例子:
public interface TestInterface<T extends TestInterface<T>> {
}
Run Code Online (Sandbox Code Playgroud)
public class Foo implements TestInterface<Foo>{
}
Run Code Online (Sandbox Code Playgroud)
public class Bar extends Foo {
}
Run Code Online (Sandbox Code Playgroud)
public class Factory {
public static <T extends TestInterface<T>> T doSth(T arg) {
return arg;
}
}
Run Code Online (Sandbox Code Playgroud)
好的,这些是我的课。现在在doSth(T arg)方法中,我想在这种情况下允许 Foo 对象,因为它是唯一“直接”实现接口的类。
显然这样的东西现在不会编译:
Bar b = Factory.doSth(new Bar());
Run Code Online (Sandbox Code Playgroud)
因为 Bar 没有实现TestInterface<Bar>.
好的,我现在的问题是,这一行将编译没有任何问题:
Foo f = Factory.doSth(new Bar());
Run Code Online (Sandbox Code Playgroud)
即使泛型参数是 T 并且 T 应该用它自己的类实现接口(抱歉,真的不知道怎么说,希望你知道我的意思),编译器接受“Bar”作为参数。
所以编译器必须表现得像“好吧,Bar 不适合,但也许超类适合。” 然后它“看到”它与超级类“Foo”一起工作。然后 Bar 将被视为 Foo,因为每个 …