www.jammni.de

Logo - Kleiner Drache
Login
Username:

Passwort:

Daten merken
Auto-Login
Registrieren
 
Online
niemand
 
Forumsuche
Suche nach:

Logo - DracheHaskell-Forum

  1 2 nächste Seite

arnold74

Gepostet:
25.04.2010 19:09

Parser und Lexer (Alex und Happy)  
Hallo,
bin Neuling in Haskell! Ich habe eine Frage zu folgendem Code. Vielleicht kann mir ja jemand weiterhelfen. Ich habe eine Aufgabe zu machen, wobei ich den Lexer von Alex und einen Parser von Happy verwenden soll. Nun leider ist mir völlig unklar, wieso nichtmal der Aufruf funktioniert. Vielleicht kann mir ja jemand sagen wie ich eine Grammatik Haskell übergeben kann.
Hier der Code von Main.hs
import Control.Monad
import qualified Lexer
import qualified Parser
import qualified Grammar

main :: IO ()
main = do content <- getContents
let grammar = Parser.statement (Lexer.alexScanTokens content)
putStrLn $ (Grammar.startSymbol grammar) ++ " {"
forM_ (Grammar.productions grammar) (putStrLn . (" " ++) . show)
putStrLn $ "}"


und dieser von Grammar.hs
module Grammar where

import qualified Data.List as List

type Variable = String
type Terminal = Char
data Symbol = V Variable | T Terminal
deriving (Eq, Ord)

data Grammar = Grammar Variable [Production]

data Production = Production Variable [Symbol]
deriving Eq

showSymbols :: [Symbol] -> String
showSymbols = concat . List.intersperse " " . map show

instance Show Symbol where
show (V v) = v
show (T t) = [t]

instance Show Production where
show (Production v symbs) = v ++ " : " ++ showSymbols symbs

instance Show Grammar where
show (Grammar v ps) = "???"

startSymbol :: Grammar -> Variable
startSymbol (Grammar x _) = x

productions :: Grammar -> [Production]
productions (Grammar _ ps) = ps


Mir ist nicht klar wie ich eine Grammatik Main übergebe. Habe schon versucht mit main E { E : n | E + E | E * E| (E)}
Habe es auch versucht direkt in eine Datei zu schreiben und Main zu übergeben mit main < meineGrammatik
aber leider alles ohne Erfolg. Es werden zwar alle Module richtig geladen, aber scheinbar ist mir noch nicht klar wie ich eine Grammatik übergebe!

danke vielmals
arnold
Zum Seitenanfang    
 
Siracusa

Gepostet:
26.04.2010 02:38

   
Hallo,

getContents liest von der Standardeingabe, d.h. im Normalfall von der Tastatur. Wenn du dein Programm compilierst zu einer Datei Main.exe, dann kannst du entweder Main starten und deine Grammatik über die Tastatur eingeben (Ende mit Strg+Z und Enter), oder die rufst das Programm so auf: Main < grammatik.txt, wobei die Datei grammatik.txt die Grammatik enthält. Wenn du main im GHCi aufrufst bleibt nur die Möglichkeit die Grammatik über die Tastatur einzugeben.


Viele Grüße,

Siracusa
Zum Seitenanfang    
 
arnold74

Gepostet:
26.04.2010 10:12

   
Danke für die schnelle Antwort Siracusa,
ich habe das doch genau so gemacht! Ich habe doch das Programm über GHCI gestartet. Alle Module werden richtig geladen. Dann rufe ich :l Main.hs auf und dann rufe ich die Funktion main auf und ich gelange zur Standareingabe, wobei zuerst die Statusmeldung loading package array-0.3.0.0... linking .. done erscheint. Wenn ich dann versuche eine Grammatik wie oben beschrieben eingebe, dann sollte doch eine Ausgabe erscheinen. Ich sollte doch dann auch weiters auf showSymbols usw zugreifen können. Ich bekomme einen Syntax error! Kann ich das über GHCI gar nicht aufsführen?

vielen Dank Siracusa
arnold
Zum Seitenanfang    
 
Siracusa

Gepostet:
26.04.2010 12:16

   
Das sollte im GHCi eigentlich auch funktionieren. Wobei mich etwas wundert, dass dein Main-Modul überhaupt compiliert, denn du importierst Funktionen aus dem Grammar-Modul, die dort zwar definiert, aber nicht exportiert werden.

Wenn du einen Syntaxfehler bekommst, liegt ja der Verdacht nahe, dass du eine falsche Grammatik eingegeben hast :-) Welchen Fehler bekommst du denn genau bei welcher Eingabe?
Zum Seitenanfang    
 
arnold74

Gepostet:
26.04.2010 18:53

   
Hallo,
vielen Dank für deine bisherige Hilfe, aber leider funktioniert es einfach nicht. Laut Angaben sollte die Grammatik in der Form E { E : n | E + E | E * E | (E) } (dies ein Beispiel) eingegeben werden. Wenn ich nun über ghci das Main.hs Modul lade werden die anderen Module richtig geladen. Dann rufe ich main auf und dann sollte ja meine Eingabe gelesen werden. Nachdem eine Grammatik dieser Form eingebe und bestätige komme ich in eine neue Zeile, aber dann nach Eingabe eines weiteren Buchstabens erscheint Exception: Syntax Error. Weiß wirklich nicht mehr weiter, danke
arnold
Zum Seitenanfang    
 
Siracusa

Gepostet:
27.04.2010 00:41

   
Hast du mal hier http://www.haskell.org/happy/doc/html/sec-grammar.html und die folgenden Seiten geschaut? Der Syntax nach müsste deine Grammatik mit einem "A : " beginnen, wobei A ein Metasymbol ist. Außerdem fehlt evtl. noch ein Header der Grammatik-Datei. Arbeite mal die Syntax durch, dann klärt sich das vermutlich.


Viele Grüße,

Siracusa
Zum Seitenanfang    
 
arnold74

Gepostet:
27.04.2010 15:44

   
Hallo,
danke für deinen Tipp, leider ist mir nicht klar wieso meine Grammatik mit einem A: beginnen sollte!
Nun ich habe versucht einige Beispiele einzugeben und es scheint, dass die eingabe einer Grammatik nach der Art:
E {E :n | E + E | E * E| (E)} bis zu diesem Punkt klappt. Dabei sollte E vor der Klammer das Startsymbol sein. Nur erscheint nun eine neue Zeile und erwartet eine weitere Eingabe , aber welche? Laut Angabe nach der Syntax
grammar ::= variable { rule 1 ; · · · ; rule n }
rule → variable : body 1 | · · · | body n
body → symbol 1 · · · symbol n
symbol → variable | terminal

und als Beispiele wurden genau die von mir angeührten Beispiele gezeigt! Irgendwie komme ich nicht weiter. Wenn ich eben in der neuen Zeile zb E eingebe erscheint folgendes:
(testmain ist mein kompilierte Hasekell Modul)
./testmain
E {E:n | E + E | E * E | (E) }
E
testmain: Syntax error

Vielen Dank und Grüße
Arnold
Zum Seitenanfang    
 
Siracusa

Gepostet:
27.04.2010 16:26

   
Hallo nochmal,

das A steht natürlich nur stellvertretend für den Namen eines Metasymbol/Nichtterminals. In dem Link oben steht doch, wie eine Regel aufgebaut sein muss:
<non-terminal> [ :: { <type> } ]
: <id> ... {[%] <expression> }
[ | <id> ... {[%] <expression> }
... ]
Das missachtest du ja schon, denn dir fehlt eine linke Seite deiner Regel. Du müsstest also z.B. mit "E : ..." beginnen.

Ohne mir die Doku für Happy jetzt genauer angeschaut zu haben, denke ich aber, dass alleine die Auflistung der Regeln nicht genügt, normalerweise sind da noch ein Datei-Header bzw. andere Deklarationen nötig. Heißt also, es wäre günstig die Grammatik direkt aus einer Datei zu lesen, statt von der Tastatur. Hier http://hackage.haskell.org/package/happy findest du den Quellcode zu Happy, da gibt es auch eine Menge Beispiele wie die .y-Dateien aufgebaut sein müssen.


*** EDIT:

Mir fällt grad auf, ich glaub ich hab dich die ganze Zeit missverstanden, dein Parser parst ja schon, d.h. das Problem ist gar nicht die Happy-Datei, sondern die Benutzereingabe :-) Also da war deine erste Zeile schon richtig (die zweite mit dem "E" verursacht den Fehler), nur stoppt getContents nicht nach einem Enter/Newline, sondern nach einen EOF-Zeichen. Das erreichst du über die Tastatur normalerweise mit Strg+Z und Enter. Damit sollte die erste Zeile eigentlich funktionieren.


Viele Grüße,

Siracusa
Zum Seitenanfang    
 
arnold74

Gepostet:
29.04.2010 10:53

   
Danke Siracusa,
genau das wars, ich habe es kompiliert und über eine Datei die Eingabe erledigt und es hat gepasst! Das mit der Tastatur wusste ich nicht, werde es jetzt gleich versuchen; das hilft mir enorm, dann kann ich die Weiterverarbeitung direkt testen!

Mir scheint Du kennst Dich sehr gut aus in Haskell, vielleicht darf ich Dich dann noch um einen Ratschlag fragen:

Wie würdest Du diese ausgegebene Grammatik weiterverarbeiten? Ich möchte gerne zu jeder Produktion ein First und FollowSet erstellen. Dazu würde ich gerne ein Tabelle in Haskell konstruieren, denke mal so Typ [(a,[a])], wobei a die Terminale ode NichtTerminale sind und [a] die Liste der Elemente von zum Beispiel First. Oder wie würdest Du es machen First :: Grammar -> ?.

Danke vielmals für deine Hilfe und Geduld

(Aller Anfang ist schwer)

Arnold
Zum Seitenanfang    
 
Siracusa

Gepostet:
29.04.2010 17:47

   
Also wenn ich mich richtig erinnere sind First und Follow ja jeweils eine Menge von Wörtern bestehend aus Terminalsymbolen zu jedem Non-Terminal. Daher würde ich first und follow vom Typ :: Grammar -> [(Variable, [[Terminal]])] definieren, also für jedes Non-Terminal eine Liste von Terminal-Wörtern (ein Wort ist vom Typ [Terminal]).
Zum Seitenanfang    
 

  1 2 nächste Seite