Ich schreibe einen Oberon-like Sprachparser, ich habe Probleme beim Kompilieren des Parsers, nachdem ich es aktualisiert habe, um mehr Prozeduren auf der gleichen Ebene zu definieren, und nicht nur verschachtelt eins in dem anderen.Haskell Happy Parser Fehler nicht übereinstimmende Typen und unendliche Art
Das ist mein Lexer:
{
module Main where
import Lexer
import Tools
}
%name myParse
%tokentype { Token }
%error { parseError }
%token
KW_PROCEDURE { KW_TokenProcedure }
KW_END { KW_TokenEnd }
';' { KW_TokenSemiColon }
identifier { TokenVariableIdentifier $$ }
%%
ProcedureDeclarationList : ProcedureDeclaration { $1 }
| ProcedureDeclaration ';' ProcedureDeclarationList { $3 : $1 }
ProcedureDeclaration : ProcedureHeading ';' ProcedureBody identifier {
do
let newProc = $1 -- Crea la nuova procedura
let procBody = $3
addProcedureToProcedure newProc procBody
}
ProcedureHeading : KW_PROCEDURE identifier { defaultProcedure { procedureName = $2 } }
ProcedureBody : KW_END { Nothing }
| DeclarationSequence KW_END { Just $1 }
DeclarationSequence : ProcedureDeclarationList { $1 }
{
parseError :: [Token] -> a
parseError _ = error "Parse error"
main = do
inStr <- getContents
let result = oLikeParse (alexScanTokens inStr)
putStrLn ("result: " ++ show(result))
}
Und das ist das Modul, in dem die Typen und einige Utility-Funktionen definiert werden:
{
module Lexer where
}
%wrapper "basic"
$alpha = [a-zA-Z]
$digit = [0-9]
$validChar = [^\"]
tokens :-
$white+ ;
"PROCEDURE" { \s -> KW_TokenProcedure }
"END" { \s -> KW_TokenEnd }
";" { \s -> KW_TokenSemiColon }
$alpha [$alpha $digit \_]* { \s -> TokenVariableIdentifier s }
{
-- The token type:
data Token =
KW_TokenProcedure |
KW_TokenEnd |
KW_TokenSemiColon |
TokenVariableIdentifier String |
deriving (Eq,Show)
}
Das ist mein Parser ist
module Tools where
data Procedure = Procedure { procedureName :: String,
procedureProcedures :: [Procedure] } deriving (Show)
defaultProcedure = Procedure { procedureName = "",
procedureProcedures = [] }
addProcedureToProcedure :: Procedure -> Maybe Procedure -> Procedure
addProcedureToProcedure procDest Nothing = Procedure { procedureName = (procedureName procDest),
procedureProcedures = (procedureProcedures procDest) }
addProcedureToProcedure procDest (Just procToAdd) = Procedure { procedureName = (procedureName procDest),
procedureProcedures = (procedureProcedures procDest) ++ [procToAdd] }
Die Fehler, die der Compiler mir gibt, sind diese zwei:
Couldn't match type ‘[Procedure]’ with ‘Procedure’
Occurs check: cannot construct the infinite type: t4 ~ [t4]
Ich habe das Problem isoliert und ich weiß sicher, dass, wenn ich den zweiten Fall meines ProcedureDeclarationList
alles kompiliert fein zu entfernen, aber ich kann nicht mehr Verfahren auf dem erkennen das selbe Level.
UPDATE
Ich habe die Struktur meiner Daten geändert, so dass ich nicht bin Maybe Procedure
mehr und ich werde Sie eine Liste von zwei Typen nicht brauchen, aber ich habe immer noch ein Problem mit unpassenden Typen .
Das ist mein aktualisiert Parser:
{
module Main where
import Lexer
import Tools
}
%name myParse
%tokentype { Token }
%error { parseError }
%token
KW_INTEGER { KW_TokenInteger }
KW_REAL { KW_TokenReal }
KW_BOOLEAN { KW_TokenBoolean }
KW_CHAR { KW_TokenChar }
KW_PROCEDURE { KW_TokenProcedure }
KW_END { KW_TokenEnd }
KW_VAR { KW_TokenVar }
';' { KW_TokenSemiColon }
',' { KW_TokenComa }
':' { KW_TokenColon }
identifier { TokenVariableIdentifier $$ }
%%
ProcedureDeclarationList : ProcedureDeclaration { [$1] }
| ProcedureDeclaration ';' ProcedureDeclarationList { $1:$3 }
ProcedureDeclaration : ProcedureHeading ';' ProcedureBody identifier { defaultDeclaration { declarationType = DT_Procedure, procedureDeclared = (addBodyToProcedure $1 $3)} }
IdentifiersList : identifier { [$1] }
| identifier ',' IdentifiersList { $1:$3 }
VariableDeclaration : IdentifiersList ':' type { createVariablesDefinitionsOfType $1 $3 }
ProcedureHeading : KW_PROCEDURE identifier { defaultProcedure { procedureName = $2 } }
ProcedureBody : KW_END { [] }
| DeclarationSequence KW_END { $1 }
DeclarationSequence : KW_VAR VariableDeclarationList ';' { $2 }
| ProcedureDeclarationList { $1 }
VariableDeclarationList : VariableDeclaration { [$1] }
| VariableDeclaration ';' VariableDeclarationList { $1:$3 }
type : KW_INTEGER { Integer }
| KW_REAL { Float }
| KW_BOOLEAN { Boolean }
| KW_CHAR { Char }
{
parseError :: [Token] -> a
parseError _ = error "Parse error"
main = do
inStr <- getContents
let result = oLikeParse (alexScanTokens inStr)
putStrLn ("result: " ++ show(result))
}
Das ist mein aktualisiert Lexer:
{
module Lexer where
}
%wrapper "basic"
$alpha = [a-zA-Z]
$digit = [0-9]
$validChar = [^\"]
tokens :-
$white+ ;
"INTEGER" { \s -> KW_TokenInteger }
"REAL" { \s -> KW_TokenReal }
"BOOLEAN" { \s -> KW_TokenBoolean }
"CHAR" { \s -> KW_TokenChar }
"PROCEDURE" { \s -> KW_TokenProcedure }
"END" { \s -> KW_TokenEnd }
"VAR" { \s -> KW_TokenVar }
";" { \s -> KW_TokenSemiColon }
"," { \s -> KW_TokenComa }
":" { \s -> KW_TokenColon }
$alpha [$alpha $digit \_]* { \s -> TokenVariableIdentifier s }
{
-- The token type:
data Token =
KW_TokenInteger |
KW_TokenReal |
KW_TokenBoolean |
KW_TokenChar |
KW_TokenVar |
KW_TokenProcedure |
KW_TokenEnd |
KW_TokenSemiColon |
KW_TokenComa |
KW_TokenColon |
TokenVariableIdentifier String |
deriving (Eq,Show)
}
Und das ist meine aktualisierte Tools Modul:
module Tools where
data AttributeType = String
| Float
| Char
| Integer
| Boolean
deriving (Show, Eq)
data Attribute = Attribute { attributeName :: String,
attributeType :: AttributeType,
stringValue :: String,
floatValue :: Float,
integerValue :: Integer,
charValue :: Char,
booleanValue :: Bool } deriving (Show)
data Procedure = Procedure { procedureName :: String,
attributes :: [Attribute],
procedureProcedures :: [Procedure] } deriving (Show)
data DeclarationType = DT_Variable
| DT_Constant
| DT_Procedure
deriving (Show, Eq)
data Declaration = Declaration { declarationType :: DeclarationType,
attributeDeclared :: Attribute,
procedureDeclared :: Procedure } deriving (Show)
defaultAttribute = Attribute { attributeName = "",
attributeType = Integer,
stringValue = "",
floatValue = 0.0,
integerValue = 0,
charValue = ' ',
booleanValue = False }
defaultProcedure = Procedure { procedureName = "",
attributes = [],
procedureProcedures = [] }
defaultDeclaration = Declaration { declarationType = DT_Variable,
attributeDeclared = defaultAttribute,
procedureDeclared = defaultProcedure }
addAttributeToProcedure :: Procedure -> Attribute -> Procedure
addAttributeToProcedure proc att = Procedure { procedureName = (procedureName proc),
attributes = (attributes proc) ++ [att],
procedureProcedures = (procedureProcedures proc) }
addProcedureToProcedure :: Procedure -> Procedure -> Procedure
addProcedureToProcedure procDest procToAdd = Procedure { procedureName = (procedureName procDest),
attributes = (attributes procDest),
procedureProcedures = (procedureProcedures procDest) ++ [procToAdd] }
addBodyToProcedure :: Procedure -> [Declaration] -> Procedure
addBodyToProcedure procDest [] = procDest
addBodyToProcedure procDest declList = do
let decl = head declList
let declType = declarationType decl
if declType == DT_Variable || declType == DT_Constant then
addBodyToProcedure (addAttributeToProcedure procDest (attributeDeclared decl)) (tail declList)
else
addBodyToProcedure (addProcedureToProcedure procDest (procedureDeclared decl)) (tail declList)
createVariablesDefinitionsOfType :: [String] -> AttributeType -> [Declaration]
createVariablesDefinitionsOfType namesList t = map (\x -> defaultDeclaration { declarationType = DT_Variable, attributeDeclared = (defaultAttribute {attributeName = x, attributeType = t})}) namesList
Dies ist das Schema die Produktionsarten:
PRODUCTION TYPE
--------------- ---------------
ProcedureDeclarationList [Declaration]
ProcedureDeclaration Declaration
IdentifiersList [String]
VariableDeclaration [Declaration]
ProcedureHeading Procedure
ProcedureBody [Declaration]
DeclarationSequence [Declaration]
VariableDeclarationList [Declaration]
type AttributeType
Dies sind die einzigen drei Fehler, die ich bekommen:
Couldn't match type ‘[Declaration]’ with ‘Declaration’
x2Couldn't match type ‘Declaration’ with ‘[Declaration]’
Ich denke, ich habe verstanden, was Sie sagen. Vielleicht kann ich dieses Problem auf andere Weise überwinden, ich meine, ich habe 'Maybe Procedure' verwendet, weil ich testen wollte, ob die Prozedur etwas im Körper hatte oder nicht. Wenn man jedoch mit der Implementierung fortfährt, können innerhalb eines Prozedurhauptteils andere Variablen als nur andere Prozeduren deklariert werden, so dass ich denke, '{Nothing}' durch '{[]}' und '{Just $ 1}' durch '{$ 1 zu ersetzen } ', so dass innerhalb von' DeclarationSequence' eine Liste zurückgegeben werden kann, die Prozeduren oder Variablen enthalten kann. Das Problem könnte sein: Wie kann ich zwei Typen in derselben Liste speichern? – zeb
Sie können nicht zwei verschiedene Typen in derselben Liste speichern. Während das nicht genau richtig ist, bedeutet es normalerweise, wenn man so denkt, dass man auf dem falschen Weg ist. Übrigens - wenn Sie etwas von dem gefunden haben, was ich hilfreich geschrieben habe, ist Upvoting angemessen und geschätzt. – ErikR
Ich habe meine Datenstruktur geändert, um 'Maybe Procedure' nicht mehr zu verwenden und ich brauche keine Liste von zwei Typen mehr. Ich habe meine Frage aktualisiert, da ich aufgrund von Typenkonflikten einige Fehler erhalte. Ich habe die Produktionstypen verfolgt, aber es hat nicht viel geholfen. – zeb