C# & ANTLR - EBNF für eine eigene Skriptsprache

Gast #2860030
Lesenswert?

Hei Leute ich versuche gerade mit ANTLR einen Parser für meine 
Scriptsprache zu schreiben. Leider scheitere ich momentan daran. Kann 
mir wer sagen was mir für diese Scriptbeispiele noch in der 
EBNF-Definition fehlt?
1
CONTROL.SET("value"=>"testwert");
2
DEFINE("name"=>"testname_fuer_variable", "value"=>0);   //Zahlen ohne Anführungszeichen
3
CONTROL.SET("value"=>CONTROL.GET("name"=>"testname"));

Mein EBNF dazu sieht bis jetzt folgendermassen aus:
1
grammar test;  
2
options
3
{
4
  language = CSharp2;
5
}
6
Statement : FunctionName'("'String'"'=>Argument');';
7
FunctionName : (Object'.SET'|Object'.GET'|'DEFINE');
8
Object : String;
9
Argument : (String|digit|Statement);
10
String   : ('a'..'z' | 'A'..'Z' | '0'..'9')+;
11
digit : ('0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9')+;

Sorry für den langen Text aber ich hab momentan wirklich irgendwie 
Gurken auf den Augen und seh den Wald vor lauter Eichhörnchen nicht 
mehr...

Bitte helft mir :)
Moderator #2860165
Lesenswert?

> 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';

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren