[Haskell-beginners] Clearing Parsec error messages
Daniel Fischer
daniel.is.fischer at web.de
Sat Jun 6 11:11:41 EDT 2009
Am Samstag 06 Juni 2009 14:26:14 schrieb Giuliano Vilela:
> On Sat, Jun 6, 2009 at 8:36 AM, Daniel Fischer <daniel.is.fischer at web.de>wrote:
> > Am Samstag 06 Juni 2009 02:05:13 schrieb Giuliano Vilela:
>
> Close, but not quite. I'm actually using the Parsec monad with my own state
> to build a symbol table during parsing (for a Pascal sub-language I
> mentioned earlier in this list). So the fail is deep in the "recursion
> chain", but it's something like what you mentioned above. It seemed to me
> that *fail* was the best way to report a error, like "undefined type
> identifier used".
Ah, I see.
You successfully parsed a list of syntactically correct declarations, then check if
they're semantically correct (using only known types, in this case) and if that fails, you
really don't want to know under which circumstances you could have parsed more
declarations :)
>
> But thinking about it now, I see my solution probably isn't optimal. In
> some cases, I will report type errors even when there is bad syntax further
> in the source, which is not common behavior. You got any suggestions for my
> use case?
If you don't want a "die on first error" strategy, add a "list of encountered errors"
component to your user state and log all encountered errors.
data ParsingState = PS
{ symTbl :: SymbolTable
, typeTbl :: TypeTable
, errs :: [SyntaxError]
}
data SyntaxError
= UnknownType SourcePos String
| UnknownOperator SourcePos String
| MissingSemicolon SourcePos
| ...
parseType = do
typeId <- Tk.identifier
tTable <- typeT
case mlookup typeId tTable of
Nothing -> return (BadType typeId)
Just typeV -> return (GoodType typeId typeV)
varDeclaration = do
varIdL <- Tk.commaSep1 Tk.identifier
Tk.symbol ":"
pos <- getPosition
tp <- parseType
case tp of
BadType typeName -> do
logError (UnknownType pos typeName)
return (VarDecl varIdL typeName)
GoodType typeName typeV -> do
forM_ varIdL (\vi -> insert vi into symbol table)
return (VarDecl varIdL typeName)
When inserting variables into the symbol table, you should check whether it's already
there, you don't want to parse
var
x, y : integer;
z, x : boolean;
without error.
I don't know what you will finally want to parse, but you should think about local
variables with the same name as one in an enclosing scope early.
Finally,
realProgram = do
prog <- program
errs <- errorList
if null errs
then return prog
else failWithErrors errs
>
> The source code for the interpreter is here:
> http://code.google.com/p/hpascal/ (pretty immature, my group just started
> writing it) if you want to take a look. Important files are: Parsing.hs
> (the parser itself) and TypeChecker.hs (parsers that access the internal
> monad state and build the table).
Hope that helps,
Daniel
More information about the Beginners
mailing list