> Statement : FunctionName'("'String'"'=>Argument');';
Der Pfeil sollte innerhalb der Apostrophe stehen:
1 | Statement : FunctionName '("' String '"=>' Argument ');';
|
> String : ('a'..'z' | 'A'..'Z' | '0'..'9')+;
Wenn String als Argument genutzt wird, fehlen die Anführungszeichen.
Ich würde String mit den Anführungszeichen definieren
1 | String : '"' ('a'..'z' | 'A'..'Z' | '0'..'9')+ '"';
|
und die Anführungszeichen in Statement weglassen:
1 | Statement : FunctionName '(' String '=>' Argument ');';
|
> Object : String;
Das stimmt jetzt nicht mehr, weil die obige Definition von String die
Anführungszeichen enthält. Darf denn ein Objektname überhaupt mit einer
Ziffer beginnen? Ich würde ein neues Element Identifier einführen:
1 | Object : Identifier;
|
2 | Identifier : Alpha AlphaNum*;
|
3 | Alpha : 'a'..'z' | 'A'..'Z';
|
4 | AlphaNum : Alpha | '0'..'9';
|
> DEFINE("name"=>"testname_fuer_variable", "value"=>0);
Da stehen mehrere "=>"-Konstrukte durch "," getrennt in einem Statement.
Das wird durch
> Statement : FunctionName'("'String'"'=>Argument');';
nicht abgedeckt. Versuch mal Folgendes:
1 | Statement : FunctionName '(' ArrowConstruct (',' ArrowConstruct)* ');';
|
2 | ArrowConstruct : String '=>' Argument;
|
Hier ist die Zusammenfassung des oben Geschriebenen:
1 | Statement : FunctionName '(' ArrowConstruct (',' ArrowConstruct)* ');';
|
2 | FunctionName : (Object '.SET' | Object '.GET' | 'DEFINE');
|
3 | ArrowConstruct : String '=>' Argument;
|
4 | Object : Identifier;
|
5 | Identifier : Alpha AlphaNum*;
|
6 | Argument : (String | Number | Statement);
|
7 | String : '"' AlphaNum+ '"';
|
8 | Alpha : 'a'..'z' | 'A'..'Z';
|
9 | Digit : '0'..'9';
|
10 | AlphaNum : Alpha | Digit;
|
11 | Number : Digit+;
|
Dabei habe ich digit durch Number (eine Zahl mit einer oder mehreren
Ziffern) ersetzt und für eine einzelne Ziffer das neue Element Digit
eingeführt.
Bei deiner Grammatik sind keine Leerzeichen und Zeilenumbrüche im Skript
erlaubt, die du aber vielleicht zur Steigerung der Übersichtlichkeit
vorsehen solltest. Meist realisiert man das dadurch, dass man dem
eigentlichen Parser einen Lexer (Scanner, Tokenizer, ...) vorschaltet,
der die Eingabe in sogenannte Tokens (z.B. String, Zahl, '(', ')', '=>'
usw.) gruppiert und zwischen diesen Tokens beliebigen Whitspace zulässt.
Der Lexer kann auch gleich die Verarbeitung von Kommentaren (wie in
deinem zweiten Beispiel) übernehmen. Ein Kommentar wird üblicherweise
wie Whitspace behandelt.
Wie man das am besten mit ANTLR umsetzt, kann ich dir jetzt aber auch
nicht sagen. Wenn ANTLR zwischen Lexer und Parser keinen Unterschied
macht, kannst du die Tokens auch wie gehabt als Produktionen in der
Grammatik definieren und jeweils ein WhiteSpace* anhängen, wobei
1 | WhiteSpace : ' ' | '\n' | '\r' | '\t';
|