String verarbeiten und ausgeben

JavaGamer

Bekanntes Mitglied
Hallo,

ich habe mal wieder ein Problem. Ich bin gerade dabei einen kleinen Parser zu schreiben, nur dieser soll die Kommentare weglassen und überprüfen ob auch alles richtig ist und den Rest danach weiter bearbeiten. Nun zu meinem Problem:

1. Jedes mal wenn die Datei eingelesen wird kommt der Inhalt nacher in komischer Form wieder raus.
2. Wie überprüfe ich, ob es zu jeder geöffneten Klammer auch eine geschlossene gibt und ob hinter jeder Anweisung (alles was keine geöffnete Klammer besitzt und kein Kommentar ist) ein Semikolon ist? (Eine Anweisung kann auch mehrere Zeilen lang sein...)

Also hier mein bisheriger Code:
Java:
	public static void checkFile(File file) throws IOException
	{
		loadFile(file);
		
		List<String> contents = new ArrayList<String>();
		
		/*Files.lines(file.toPath())
			.map(s -> s.trim())
			.filter(s -> !s.isEmpty())
			.forEach(s -> lines.add(s));*/
		
	    List<String> lines = Files.lines(file.toPath())
	    	    .map(s -> s.trim())
	    	    .filter(s -> !s.isEmpty())
	    	    .collect(Collectors.toList());
		
		for(int i = 0; i < lines.size(); i++)
		{
			String check = lines.get(i);
			
			if(check.contains("//"))
			{
				int position = check.indexOf("//");
				
				//String result = check.substring(position, check.length());
				String result = check.substring(0, position);
				contents.add(result);
			}
			else
				contents.add(check);
		}
		
		for(int i = 0; i < contents.size(); i++)
		{
			System.out.println(contents.toString());
		}
	}

Die Datei selbst:
Code:
include <platformer_v1>

class story_level_1.shd
{
	init()
	{
		game:s_level=1; // the png and shd file of the level
		
		x:start = 1; // the start point to load from
		x:end = 49; // the end point to load
		x:spawn=3; // the spawn point
		x:portal=47; // the portal point
		
		y:start = 1;
		y:end = 22;
		y:spawn=3;
		y:portal=10;
	}
	
	tick()
	{
		if(player == portal)
			level++;
		
		if(player == from 'x:start' to 'x:end')
			level;
		
		if(player == from 'y:start' to 'y:end')
			level;
		
		if(player == (from 'y:end' & 'x:start' to 'y:end' & 'x:end'))
			level;
		
		if(player == (from 'x:end' & 'y:start' to 'x:end' & 'y:end'))
			level;
	}
	
	render()
	{
		game:color_dirt=255,0,0;
		game:color_bedrock=127,0,0;
		game:color_background=0,0,0;
	}
}

Und zum Schluss der momentanige output, der ein wenig falsch ist (so sieht jede Zeile vom output aus, darum hier nur eine Zeile):
Code:
[include <platformer_v1>, class story_level_1.shd, {, init(), {, game:s_level=1; , x:start = 1; , x:end = 49; , x:spawn=3; , x:portal=47; , y:start = 1;, y:end = 22;, y:spawn=3;, y:portal=10;, }, tick(), {, if(player == portal), level++;, if(player == from 'x:start' to 'x:end'), level;, if(player == from 'y:start' to 'y:end'), level;, if(player == (from 'y:end' & 'x:start' to 'y:end' & 'x:end')), level;, if(player == (from 'x:end' & 'y:start' to 'x:end' & 'y:end')), level;, }, render(), {, game:color_dirt=255,0,0;, game:color_bedrock=127,0,0;, game:color_background=0,0,0;, }, }]

Würde man jetzt den Output so haben wie er fast sein sollte:
Code:
[include <platformer_v1>, 
class story_level_1.shd, 
{, 
init(), 
{, 
game:s_level=1; 
, x:start = 1; 
, x:end = 49; 
, x:spawn=3;
 , x:portal=47; 
, y:start = 1;
, y:end = 22;
, y:spawn=3;
, y:portal=10;
,
 }, 
tick(), 
{,
 if(player == portal), 
level++;, 
if(player == from 'x:start' to 'x:end'),
 level;,
 if(player == from 'y:start' to 'y:end'),
 level;,
 if(player == (from 'y:end' & 'x:start' to 'y:end' & 'x:end')), 
level;,
 if(player == (from 'x:end' & 'y:start' to 'x:end' & 'y:end')), 
level;, 
},
render(), 
{, 
game:color_dirt=255,0,0;
, game:color_bedrock=127,0,0;
, game:color_background=0,0,0;
, }
, }]
Ich denke mal jedem ist aufgefallen das hier mehr Kommans als vorher drinnen sind und das die eckigen Klammern da auch nicht hingehören. Ob dort etwas fehlt habe ich jetzt aber nicht geprüft, da ich das dafür erstmal wieder so schön lesbar haben möchte wie vorher...

Und zudem soll ja Teil zwei des Problems überprüfen ob alles da ist und richtig ist. (Schade dass es hier im Forum anscheinend keine Spoiler mehr gibt...)

Ich hoffe jemand kann mir hierbei helfen.
JavaGamer
 
Zuletzt bearbeitet:
D

daersc

Gast
Hallo JavaGamer,


Ich hab auch schon mal versucht, einen kleinen Java-Parser zu implementiere. Mir war damals allerdings nur das Auffinden von String-Literalen wichtig und ich habe alles andere ignoriert. Die String-Literale habe ich mit ihrer Position in einer Map gespeichert.

1. Jedes mal wenn die Datei eingelesen wird kommt der Inhalt nacher in komischer Form wieder raus.

In deinem Fall liegt das nicht am Einlesen, sondern am Rausschreiben. In Zeile 36 iterierst du über den gesamten Inhalt (mit der Zählervariable i) und gibst jedes mal per
Code:
System.out.println(contents.toString());
den gesamten Inhalt der Liste aus (der eben standardmäßig mit den eckigen Klammern und Kommata zwischen allen Elementen der Liste dargestellt wird).

Versuche es stattdessen mit
Code:
System.out.println(contents.get(i));
Dafür hast du ja schließlich über die Liste iteriert.


2. Wie überprüfe ich, ob es zu jeder geöffneten Klammer auch eine geschlossene gibt und ob hinter jeder Anweisung (alles was keine geöffnete Klammer besitzt und kein Kommentar ist) ein Semikolon ist? (Eine Anweisung kann auch mehrere Zeilen lang sein...)

Das Zeilenweise Einlesen der Datei würde ich ehrlich gesagt nicht machen - Alleine aus dem Grund, dass einzelne Zeilen in Java in der Regel keine Bedeutung haben. Stattdessen würde ich eher einen Zeichenweisen Stream verwenden und auch die Zeilenumbrüche einlesen und manuell verarbeiten.


Um öffnende und schließende Klammern habe ich mich damals per Rekursion gekümmert: Jede öffnende Klammer ruft die eigene Methode (mit dem "Klammertyp" als Parameter) auf. Eine schließende Klammer vom entsprechenden Klammertyp beendet hingegen die Methode. Wenn das Dateiende zwischendurch erreicht ist, sind die Klammern unvollständig.

Edit: Natürlich sind die Klammern auch dann unvollständig, wenn eine schließende Klammer vom falschen Klammertyp gefunden wird.

Das gleiche sollte man aber auch mit Kommentaren machen! Also zum Beispiel "/*" oder "//" wird als Anfang einer Kommentar-Umgebung gesehen während "*/" oder ein Zeilenende den Kommentar beendet.

Auf ähnliche Weise könntest du auch überprüfen, ob ein Statement korrekt mit einem Semikolon geschlossen wurde - nur das Erkennen des Beginns eines Statements dürfte dann etwas schwerer ausfallen.


Viel Erfolg!

daersc
 
Zuletzt bearbeitet von einem Moderator:

Network

Top Contributor
Naja theoretisch kannst du auch einfach die Klammer-Auf und Klammer-Zu zählen.
Übersteigt die Klammer-Zu Zahl die Auf Zahl zu irgendeinem Punkt weißt du es gibt zu viele Klammer-Zu.
Übersteigt die Klammer-Auf Zahl die Klammer-Zu Zahl am Ende fehlen Klammer-Zu.

Wo die Klammern fehlen oder zu viel sind lässt sich logisch nicht ermitteln.


Ob ein Semikolon fehlt lässt sich feststellen (oder besser: vermuten) wenn am Ende einer Anweisung kein Semikolon oder kein Punkt steht oder keine Klammer-Auf/Zu oder ein Operator.
 
Zuletzt bearbeitet:
D

daersc

Gast
Naja theoretisch kannst du auch einfach die Klammer-Auf und Klammer-Zu zählen.

Da bin ich anderer Meinung. Nach dieser Methode wäre ein Konstrukt wie
Java:
{
    System.out.println("Hallo"
} )
in Ordnung, denn die Anzahl stimmt ja.

Hingegen wenn ich die Sache rekursiv löse, und in einer Variable gespeichert habe, welche Klammer als nächstes kommen muss, damit das syntatkisch in Ordnung ist, kann ich sofort ganz genau angeben, dass ein Klammerfehler existiert und sogar wo genau - nämlich dort, wo eine unerwartete schließende Klammer auftaucht.
 
Zuletzt bearbeitet von einem Moderator:

Network

Top Contributor
Wenn du es richtig machst geht das schon.
Noch eine kleine Zählerlogik mit einbauen und fertig, bitte nicht stupider hinstellen als es ist.

Hab auh nicht gesagt das deine Lösung falsch ist, habe einfach nur eine iterative Alternative gezeigt,
bin einfach kein Fan von Rekursion.
Rekursieren machen die Mathematiker, richtige Softwaretechniker iterieren.

Und deine rekursive Lösung weiß auch nicht immer wo die Klammer fehlt oder zuviel ist.
Bei deinem genannten Fehler sind zwei Klammern vertauscht, hat aber nichts mit dem eigentlichen Problem das eine Klammer fehlt oder zuviel ist.
Das kann man nur erahnen durch genaue Code Analyse wo wahrscheinlich die Klammer fehlt, aber das wäre auch nicht immer korrekt und ein großer Aufwand.
 
D

daersc

Gast
Sorry, so sollte das nicht rüber kommen.

Ich denke nur, es wäre iterativ recht schwierig sich zu merken, welche schließende Klammer als nächstes kommen sollte, und sich das auch über das Ende eines inneren Klammer-Paares hinaus zu merken. Dafür würde sich beispielsweise ein Stack eignen, der sich eben mehrere Zeichen merkt - aber dann kann man doch auch gleich den Methoden-Aufruf-Stack zunutze machen. Das macht das ganze übersichtlicher (in meinen Augen - die tatsächlich die eines Mathematikers sind ;) )


Das kann man nur erahnen durch genaue Code Analyse wo wahrscheinlich die Klammer fehlt, aber das wäre auch nicht immer korrekt und ein großer Aufwand.

Ja das ist richtig. Der Aufwand ist wohl IMMER zu groß. Nützt ja nicht viel, wenn die Software so schlau ist, dass sie Fehler so genau erkennt, dass sie sie selbst beheben kann - dann bräuchte man ja kaum noch eine Syntax einzuhalten.

Auch die meisten Compiler geben ja nur solche Dinge wie "unerwartete Klammer" aus, wenn eine Klammer an früherer Stelle fehlt.
 

JavaGamer

Bekanntes Mitglied
Danke für eure Antworten, damit konnte ich das erste Problem lösen und beim zweiten scheint mir der von @daersc beschriebene Weg der bessere zu sein, jedoch habe ich keine Ahnung wie ich das umsetzten soll.
Und was ist eine Rekursion und was ist eigentlich der Unterschied zwischen Rekursion und iterativ?
 

keddelzz

Mitglied
Guten Abend,

eine Programmiersprache (auch wenn sie selbst ausgedacht ist) zu parsen ist je nachdem welche Konstrukte sie unterstützt nicht so einfach umzusetzen.

Lass mich dir grob erklären wie man (Bauer einer Programmiersprache) das macht:
1.) Man programmiert einen Scanner. - Ein Scanner ließt eine Quelltextdatei ein und fasst Zeichen zu sog. "Tokens zusammen". Ein Token ist ein "Wort" der Programmiersprache.
Der Code
Code:
variable = 3 + 7;
könnte zum Beispiel durch folgende Tokens repräsentiert werden:
Code:
IDENTIFIER("variable")
EQUALS
NUMBER(3)
PLUS
NUMBER(7)
SEMICOLON

Um einen Scanner zu programmieren, muss man jedoch nicht das Rad neu erfinden! Man kann auch sog. Scannergeneratoren zu Hilfe nehmen. (In meiner Uni nehmen wir JFlex - JFlex - The Fast Scanner Generator for Java)

Allerdings muss man sich erst ein bisschen in diesem Hilfswerkzeug einarbeiten.

2.) Nachdem man alle Tokens der Programmiersprache hat, kommt der schwierigere Teil: Das Parsen.
Das Parsen ist jedoch wesentlich komplexer als das Scannen, denn jetzt betrachtet man nicht nur die einzelnen Worte der Programmiersprache, sondern auch den Kontext in dem sie stehen (also z.B. Variablendefinition IN einer Methode, oder Methodendeklaration in einer Klasse).

Man definiert die Sprache mit einer sog. Kontextfreien Grammatik (Kontextfreie Grammatik) aus dieser Grammatik generiert man mit einem Pasergenerator (wie Java Cup CUP oder ANTLR ANTLR) dann den Parser.

Im Fach Compilerbau benutzen wir das Tool Java Cup. Die Bedienung des Tools zu verstehen war eine kleine Herausforderung, aber ich arbeite jetzt gerne damit.

Der Parser spuckt ein Java-Objekt aus, welches der sog. "Syntaxbaum" ist.
Durch den Baum kann man dann durchgehen und die gewünschten Aktionen durchführen. (zB. Codegenerierung beim Compilieren oder ausführen von Code beim Interpretieren)


Neben dem Studium beschäftige ich mich momentan viel mit der Programmiersprache Scala. Für die gibt es eine Bibliothek die meiner Meinung nach besser verständlich ist, als die Tools JFlex und Java Cup (https://github.com/scala/scala-parser-combinators). Allerdings will ich damit nicht sagen, dass du zwingend jetzt die Sprache Scala lernen musst, um erfolgreich einen Parser zu programmieren.


Man kann auch ohne die Tools einen Scanner / Parser bauen, allerdings frage ich mich auch: Warum das Rad neu erfinden?

Ich hoffe du kannst mit meiner Antwort etwas anfangen :D

mfg - keddelzz
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
H RXTX String verarbeiten Allgemeine Java-Themen 1
OnDemand Java String in Hashmap als Key NULL Allgemeine Java-Themen 27
JAnruVA Datentypen Berechneten String-Wert in Double umwandeln um weiter zu rechnen Allgemeine Java-Themen 7
M String Allgemeine Java-Themen 10
M Suche nach String mit unbekannten characters Allgemeine Java-Themen 53
kodela String kann nicht zu Pfad konvertiert werden Allgemeine Java-Themen 16
melaniemueller Einzelne Zeile aus einer txt Datei in einem String speichern Allgemeine Java-Themen 12
E Objekte in einen String packen und wieder laden Allgemeine Java-Themen 5
M Map<String,String>funktioniert nicht richtig Allgemeine Java-Themen 4
O String in Long Hexerdezimal umwandel Allgemeine Java-Themen 14
N String vergleichen. Allgemeine Java-Themen 27
P String.replace() funktioniert nicht? Allgemeine Java-Themen 3
SaschaMeyer Arbeitet String.split falsch? Allgemeine Java-Themen 4
M Switches ohne String Allgemeine Java-Themen 18
AmsananKING String Iteration Allgemeine Java-Themen 5
S Shuffle String aus if-clause Allgemeine Java-Themen 11
Besset Variablen Ist String = "" + int inordnung? Allgemeine Java-Themen 6
M Map <Long, String> zu Map<String, Long> Allgemeine Java-Themen 9
S String Encoding Verständnisproblem Allgemeine Java-Themen 22
N Prüfen, ob ein String 2x das selbe Zeichen hat Allgemeine Java-Themen 10
SaftigMelo Bug Fixen von String-spliten Allgemeine Java-Themen 8
Monokuma String List nach Zahlen und Worten sortieren Allgemeine Java-Themen 9
Kingamadeus2000 Alle mehrfach vorkommenden Buchstaben rekursiv aus einem String entfernen. Allgemeine Java-Themen 6
YohnsonM String - Aufteilung und Nutzung einzelner Chars Allgemeine Java-Themen 7
O Formatierte String ausgabe bei vier Variablen in einer Zeile Allgemeine Java-Themen 1
S String umbenennen: wie? Allgemeine Java-Themen 4
x46 String Format Fehler Allgemeine Java-Themen 2
S ISO 8601 -> getter / setter String Allgemeine Java-Themen 3
L String zu repräsentativen Wert Allgemeine Java-Themen 0
H Array mit dem Datentype String[] initializieren Allgemeine Java-Themen 7
L ArrayList mit String Arrays in ein Array umwandeln Allgemeine Java-Themen 1
L regex ganzer string? Allgemeine Java-Themen 2
L Ist ein string ein erlaubter variabel name? Allgemeine Java-Themen 2
Z JNA Cpp-DLL String Verwendung Allgemeine Java-Themen 2
A String auf Zahlen überprüfen Allgemeine Java-Themen 5
N String Array Eingabe Allgemeine Java-Themen 6
MiMa Datum von String zu LocalDateTime Allgemeine Java-Themen 8
W String -> byte[] -> String - Sieht jemand was ich nicht sehe? Allgemeine Java-Themen 10
R char aus String entfernen Allgemeine Java-Themen 10
LimDul Mittels Streams aus Strings A B C den String A, B und C machen Allgemeine Java-Themen 12
M Programm erkennt String aus .txt Datei nicht Allgemeine Java-Themen 3
P einen public <Optinal String> in einer anderen Klasse mit einem Int vergleichen Allgemeine Java-Themen 2
S Ini Text aus String parsen Allgemeine Java-Themen 1
T String-Manipulation beim Ablauf in Eclipse und als JAR-File Allgemeine Java-Themen 8
M String lässt sich nicht Zusammenfügen Allgemeine Java-Themen 10
Drachenbauer Wie kann ich das Wort "concrete" in einem String durch ein anderes Wort ersetzen lassen? Allgemeine Java-Themen 5
R Schlüsselworte "Throw new exception" gibt nicht den String als Fehlermeldung aus Allgemeine Java-Themen 2
R Variablen String mit split-Funktion aufteilen Allgemeine Java-Themen 7
F Datei in String-Array einlesen Allgemeine Java-Themen 8
S Marker aus String ermitteln Allgemeine Java-Themen 5
T Objekt mit String und Int aus TxT Datei erstellen Allgemeine Java-Themen 23
M Bei String.format ein Komma statt einem Punkt ausgeben lassen Allgemeine Java-Themen 1
S MSSQL Exception & Connection String Allgemeine Java-Themen 19
B Bei Email: FW / AW... - Hilfe bei String suche Allgemeine Java-Themen 21
J String - Vergleiche Allgemeine Java-Themen 7
K Aus String zwei Jahreszahlen auslesen Allgemeine Java-Themen 18
Drachenbauer Wie kann eine vorgegebene Farbe über einen String erkannt werden? Allgemeine Java-Themen 11
G CSV in String Allgemeine Java-Themen 7
P String-Verschlüsselung - Frage zur Sicherheit Allgemeine Java-Themen 21
K Methodenaufruf mit String / String zu Objekt konvertieren Allgemeine Java-Themen 8
D Erste Schritte Fehler mit negativen und 0 Zahlen im String Allgemeine Java-Themen 6
Xge Replace x Zeichen aus String Allgemeine Java-Themen 2
coolian warum bekomme ich ein string index out of bounds exception Allgemeine Java-Themen 17
F In String 2 Buchstaben vertauschen Allgemeine Java-Themen 2
J Class Decompile als String (Procyon) Allgemeine Java-Themen 2
I Datentypen String in class sicher verwahren Allgemeine Java-Themen 17
J Falls der String ein "X" beinhaltet Allgemeine Java-Themen 2
T String mehrere Worte Allgemeine Java-Themen 2
D String Groß-/Kleinschreibung Allgemeine Java-Themen 2
D String und Klassenvariable Allgemeine Java-Themen 6
Aruetiise Funktion(y = mx+n) in String speichern und berechnen Allgemeine Java-Themen 9
C String in Objektnamen umwandeln Allgemeine Java-Themen 3
E Variablen Aus .txt ausgelesener string mit if() überprüfen? Allgemeine Java-Themen 2
L String-Schema-Aufspaltung Allgemeine Java-Themen 2
E String in Zahl umwandeln, ohne Befehl Integer.parseInt Allgemeine Java-Themen 3
L String splitten und multiplizeren Allgemeine Java-Themen 10
G String mit umbekannter länge splitten. Allgemeine Java-Themen 2
S Einzigartigen String in Datenbank finden und löschen Allgemeine Java-Themen 23
A Byte zu String Allgemeine Java-Themen 4
B Von String zu <Objekt> ||Speichern/Laden Allgemeine Java-Themen 17
T Komplexitätsoptimierung String vergleich Allgemeine Java-Themen 4
heinz ketchup String im JLabel ausgeben und erneuern Allgemeine Java-Themen 6
S Input/Output Beste Möglichkeit einen String in einen Datei zu Schreiben Allgemeine Java-Themen 2
V Eingegeben String Splitten und in Integer umwandeln Allgemeine Java-Themen 2
L Decrypt String Allgemeine Java-Themen 1
X Variablen AtmicLong größer als String ? Allgemeine Java-Themen 4
S String literal und Referenzvariablen Allgemeine Java-Themen 6
J Datentypen Absätze mit String im Word Dokument Allgemeine Java-Themen 3
D "Paste" String doppelt Allgemeine Java-Themen 14
E String Frage Allgemeine Java-Themen 9
T String aus While Schleife für ganze Klasse sichtbar machen Allgemeine Java-Themen 5
D JSON to String Allgemeine Java-Themen 31
M String automatisch in nächste Zeile umbrechen (Graphics) Allgemeine Java-Themen 6
U Methoden Algorithmus MergeSort String [ ] array sortieren programmieren Allgemeine Java-Themen 17
T Swing Font String Pixellänge Allgemeine Java-Themen 1
G Substrings in einen String zusammenfassen Allgemeine Java-Themen 5
Tommy Nightmare String.replaceAll(...) fehlerhaft? Allgemeine Java-Themen 3
L String auf zahlenwert prüfen Allgemeine Java-Themen 13
U OOP Warum kann ich aus meiner Methode keinen String auslesen Allgemeine Java-Themen 4
L 2-Dimensionaler String: Zahlen verschieben Allgemeine Java-Themen 10

Ähnliche Java Themen

Neue Themen


Oben