Antlr Grammatik übersetzt ohne Fehler, dennoch wird Zahl nicht als Eingabe erkannt

Skrodde

Aktives Mitglied
Hallo zusammen,
ich habe mir nach einer Einarbeitung in Antlr folgende Grammatik geschrieben:
Code:
grammar Function;

parseFunction returns [java.util.List<java.util.List<Object>> list]	:	
		{ list = new java.util.ArrayList(); }                      	                   ( f=functionPart { list.add($f.list); } )+
	|	{ list = new java.util.ArrayList(); } ( fb=functionBegin ) { list.add($fb.list); } ( f=functionPart { list.add($f.list); } )*
	;
	
functionBegin returns [java.util.List<Object> list]:
	m=NUMBER v=VARIABLE e=exponent 	{ list = new java.util.ArrayList(); list.add("+"); list.add($m.text); list.add($v.text); list.add($e.value); }
	| m=NUMBER v=VARIABLE 		{ list = new java.util.ArrayList(); list.add("+"); list.add($m.text); list.add($v.text); }
	| v=VARIABLE e=exponent 	{ list = new java.util.ArrayList(); list.add("+"); list.add("1");     list.add($v.text); list.add($e.value); }	
	| v=VARIABLE 			{ list = new java.util.ArrayList(); list.add("+"); list.add("1");     list.add($v.text); }
	| m=NUMBER 			{ list = new java.util.ArrayList(); list.add("+"); list.add($m.text); }
	;
	
functionPart returns [java.util.List<Object> list] :	
	s=SIGN m=NUMBER v=VARIABLE e=exponent 	{ list = new java.util.ArrayList(); list.add($s.text); list.add($m.text); list.add($v.text); list.add($e.value); }
	| s=SIGN m=NUMBER v=VARIABLE 		{ list = new java.util.ArrayList(); list.add($s.text); list.add($m.text); list.add($v.text); }
	| s=SIGN v=VARIABLE e=exponent 		{ list = new java.util.ArrayList(); list.add($s.text); list.add("1");     list.add($v.text); list.add($e.value); }
	| s=SIGN v=VARIABLE 			{ list = new java.util.ArrayList(); list.add($s.text); list.add("1");     list.add($v.text); }
	| s=SIGN m=NUMBER 			{ list = new java.util.ArrayList(); list.add($s.text); list.add($m.text); }
	;

exponent returns [int value]: ('^' n=INTEGER) { $value = 1; if ( $n != null && $n.text.length() > 0) $value = Integer.parseInt($n.text); }
	;

VARIABLE	: ('a'..'z'|'A'..'Z')+
	;
	
INTEGER : ('0'..'9')+
	;
	
NUMBER	: ('0'..'9')+(','('0'..'9')+)?
	;
	
SIGN 	:	('+'|'-')
	;

WS  :    (' ' | '\t' | '\r'| '\n')+ {skip();} 
	;
Diese soll Polynome in mehreren Variablen ermöglichen, wobei der führende Term kein Vorzeichen haben muss. Beispiele:
Code:
1337; X^42; Y^1337-42X; +42HalloWelt^1337
Ich lasse mir die Grammatik also von Antlr übersetzen und nutze die erstellte
Code:
FunctionLexer.java
und
Code:
FunctionParser.java
. Bis auf eine werden folgende Eingaben werden nun auch akzeptiert:

Java:
	public static void main(String[] args) throws Exception {
		System.out.println(parserTest("X"));
		System.out.println(parserTest("+X"));
		System.out.println(parserTest("-X"));
		System.out.println(parserTest("HalloWelt+42,13X^13-X^2"));
		System.out.println(parserTest("42,1337"));
		System.out.println(parserTest("X+42+X")); //<-- Hier gibt es einen Fehler
	}

	private static List<List<Object>> parserTest(String input) throws RecognitionException {
		ANTLRStringStream in = new ANTLRStringStream(input);
        FunctionLexer lexer = new FunctionLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        FunctionParser parser = new FunctionParser(tokens);
        return parser.parseFunction();
	}
Der Fehler scheint aufzutauchen, wenn ich eine Zahl, die kein Komma beinhaltet, verwende. Kann mir jemand von euch auf die Sprünge helfen, woran es hier liegt?
Gruß, Skrodde
 
Zuletzt bearbeitet:

Skrodde

Aktives Mitglied
Bei den Kollegen von stackoverflow.com habe ich den Fehler lösen können. Es liegt daran, dass die erste Lexer Regel mit dem längsten Treffer "gewinnt". Daher wird 42 immer als INTEGER interpretiert und NUMBER in der Tat nur, falls sie ein Komma beinhaltet. Das Problem kann durch folgenden Work-Around erledigt werden:

Code:
number : NUMBER | INTEGER;

Wobei jedes Vorkommen von NUMBER in den oberen Codezeilen durch number ersetzt wird.
 

HoaX

Top Contributor
functionBegin und functionPart sind sich ziemlich ähnlich ... würde ich nicht so machen. Vor allem wenn es komplexer wird schreibst du sonst vieles doppelt und dreifach.
 

HoaX

Top Contributor
Im Prinzip kannste das ja einfach kürzen: (ungetestet)
Code:
functionPart returns [java.util.List<Object> list] :
        s=SIGN f=functionBegin { list = $f.list; list.set(0, $s.text); }
 

Ähnliche Java Themen

Neue Themen


Oben