Forum: PC-Programmierung C# & ANTLR - EBNF für eine eigene Skriptsprache


von Farin (Gast)


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 :)

von Yalu X. (yalu) (Moderator)


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

von Farin (Gast)


Lesenswert?

Wow herzlichen Dank!
Das mit den Strings habe ich auch schnell gemerkt. :)
Deine Lösung ist super Yalu.
Ich danke dir vielmals. Ohne dich hätte ich wahrscheinlich schon 
aufgegeben. ^^

Gruss

Farin

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.