Skip to content

Commit

Permalink
Better error messages. Closes #4
Browse files Browse the repository at this point in the history
  • Loading branch information
rampelstinskin committed Feb 15, 2012
1 parent 2fff408 commit 2b1312f
Show file tree
Hide file tree
Showing 15 changed files with 139 additions and 22 deletions.
30 changes: 24 additions & 6 deletions N2Perser/Main.n
Expand Up @@ -166,25 +166,43 @@ module Program
match (parser.ParseStart(code)) match (parser.ParseStart(code))
{ {
| None => | None =>
WriteLine($"Fail: \"$code\""); WriteLine($"Fail:\n\"$code\"");
def (pos, rules) = parser.Parser.GetErrors(); def (pos, tokens) = parser.Parser.GetErrors();
def (line, pos) = parser.ParsingSource.PositionToLineColumn(pos); def (line, pos) = parser.ParsingSource.PositionToLineColumn(pos);
foreach (rule in rules) foreach (token in tokens)
WriteLine($" $line:$pos $(rule.Grammar.Name).$(rule.Name)"); WriteLine($" $line:$pos expected \"$(token.Name)\" in rule $(token.Rule.Grammar.Name).$(token.Rule.Name)");

| Some(ast) => | Some(ast) =>
//WriteLine($"Ok: \"$code\" AST: $(printAst(ast))"); //WriteLine($"Ok: \"$code\" AST: $(printAst(ast))");
_ = ast; _ = ast;
WriteLine("OK"); WriteLine($"OK:\n\"$code\"");
} }
WriteLine();
} }


test(<# test(<#
namespace Ns1 namespace Ns1
{
using N2ParserExtensions.N2ParserExtension1
type X - A.B;
}
#>);

test(<#
namespace Ns1
{
using N2ParserExtensions.N2ParserExtension1;
type X - A.B;
}
#>);

test(<#
namespace Ns1
{ {
using N2ParserExtensions.N2ParserExtension1; using N2ParserExtensions.N2ParserExtension1;
type X = A.B; type X = A.B;
} }
#>); #>);
_ = ReadLine(); _ = ReadKey();
} }
} }
Expand Up @@ -14,6 +14,14 @@ namespace Nemerle.Parser
{ {
partial internal class GrammarCompiler partial internal class GrammarCompiler
{ {
private _tokenDescriptors : Hashtable[RuleDefinition, list[string]] = Hashtable();
[Memoize]
public GetTokenDescriptor(name : string, rd : RuleDefinition) : PExpr
{
_ = _tokenDescriptors.Update(rd, [], names => name :: names);
<[ $(GrammarImplTB.Name : dyn).$(GrammarDescriptorImplTB.Name : dyn).$(DecorateRuleClassName(rd) : dyn).$($"_token_$(name)_" : dyn) ]>
}

public DefineDescriptors() : void public DefineDescriptors() : void
{ {
foreach (rd in ParsedGrammar.Rules) foreach (rd in ParsedGrammar.Rules)
Expand All @@ -31,6 +39,9 @@ namespace Nemerle.Parser
} }
]>; ]>;
def tb = GrammarDescriptorImplTB.DefineNestedType(descriptorClass); def tb = GrammarDescriptorImplTB.DefineNestedType(descriptorClass);
when (_tokenDescriptors.Contains(rd))
foreach (name in _tokenDescriptors[rd])
tb.Define(<[decl: public static $($"_token_$(name)_" : dyn) : Nemerle.Parser.TokenDescriptor = Nemerle.Parser.TokenDescriptor(_staticDescriptor, $(name : string)) ]>);
match (GetRuleType(rd.Name)) match (GetRuleType(rd.Name))
{ {
| RuleType.NType(type) => tb.Define(<[decl: public ResultType() : $(type : typed) { mutable res; res } ]>) | RuleType.NType(type) => tb.Define(<[decl: public ResultType() : $(type : typed) { mutable res; res } ]>)
Expand Down
Expand Up @@ -16,7 +16,20 @@ namespace Nemerle.Parser
{ {
private DefineParsingErrors() : void private DefineParsingErrors() : void
{ {
def rules = ParsedGrammar.Rules.Filter(rd => !(rd is RuleDefinition.ExternalRule)); def rules = ParsedGrammar.Rules.Filter(rd =>
match (rd : RuleDefinition)
{
| ExtentionPoint
| Regular
| ExternalRule
=> false

| ExtentionPrefix
| ExtentionPostfix
| Simple
=> true
});

def getErrors = rules.Map(rd => def getErrors = rules.Map(rd =>
{ {
def name = DecorateRuleName(rd); def name = DecorateRuleName(rd);
Expand All @@ -27,13 +40,13 @@ namespace Nemerle.Parser
descriptors.Clear(); descriptors.Clear();
} }
when (pos == $(name : dyn)) when (pos == $(name : dyn))
descriptors.Add(GrammarDescriptorImpl.$(DecorateRuleClassName(rd) : dyn).StaticDescriptor); descriptors.Add($(DecorateTokenDescriptor(rd) : dyn));
]> ]>
}); });
def clear = rules.Map(rd => <[ $(DecorateRuleName(rd) : dyn) = -1; ]>); def clear = rules.Map(rd => <[ $(DecorateRuleName(rd) : dyn) = -2; $(DecorateTokenDescriptor(rd) : dyn) = null; ]>);


_ = ParsingErrorsTB.DefineWithSource(<[decl: _ = ParsingErrorsTB.DefineWithSource(<[decl:
public override GetErrors(pos : ref int, descriptors : SCG.List[RuleDescriptor]) : void public override GetErrors(pos : ref int, descriptors : SCG.List[Nemerle.Parser.TokenDescriptor]) : void
{ {
_ = pos; _ = pos;
_ = descriptors; _ = descriptors;
Expand All @@ -49,7 +62,10 @@ namespace Nemerle.Parser
]>); ]>);


foreach (rd in rules) foreach (rd in rules)
{
_ = ParsingErrorsTB.DefineWithSource(<[decl: public mutable $(DecorateRuleName(rd) : dyn) : int ]>); _ = ParsingErrorsTB.DefineWithSource(<[decl: public mutable $(DecorateRuleName(rd) : dyn) : int ]>);
_ = ParsingErrorsTB.DefineWithSource(<[decl: public mutable $(DecorateTokenDescriptor(rd) : dyn) : Nemerle.Parser.TokenDescriptor ]>);
}
} }
} }
} }
5 changes: 5 additions & 0 deletions Nemerle.Parser.Macro/Compiler/GrammarCompiler/Decorate.n
Expand Up @@ -25,6 +25,11 @@ namespace Nemerle.Parser
DecorateRuleName(rd.Name) DecorateRuleName(rd.Name)
} }


public DecorateTokenDescriptor(rd : RuleDefinition) : string
{
DecorateRuleName(rd.Name) + "_token_descriptor_"
}

public DecorateRuleClassName(rd : RuleDefinition) : string public DecorateRuleClassName(rd : RuleDefinition) : string
{ {
match (rd) match (rd)
Expand Down
Expand Up @@ -32,8 +32,7 @@ namespace Nemerle.Parser
if (newPos > 0) if (newPos > 0)
$setResult; $setResult;
else else
when (_grammar._parsingErrors.$(_grammarCompiller.DecorateRuleName(rd) : dyn) < pos) $(SetParsingErrorCode($"#$(rd.Name)"));
_grammar._parsingErrors.$(_grammarCompiller.DecorateRuleName(rd) : dyn) = pos;
newPos; newPos;
]>) ]>)
} }
Expand Down
Expand Up @@ -31,8 +31,7 @@ namespace Nemerle.Parser
if (newPos > 0) if (newPos > 0)
$setResult; $setResult;
else else
when (_grammar._parsingErrors.$(_grammarCompiller.DecorateRuleName(rd) : dyn) < pos) $(SetParsingErrorCode($"#$(rd.Name)"));
_grammar._parsingErrors.$(_grammarCompiller.DecorateRuleName(rd) : dyn) = pos;
newPos newPos
]>) ]>)
} }
Expand Down
10 changes: 9 additions & 1 deletion Nemerle.Parser.Macro/Compiler/RuleCompiler/CompileRuleString.n
Expand Up @@ -28,7 +28,15 @@ namespace Nemerle.Parser
def exprs = rule.str.Select(makeCharCheckCode); def exprs = rule.str.Select(makeCharCheckCode);
def condExpr = exprs.Aggregate((e1, e2) => <[ $e1 && $e2 ]>); def condExpr = exprs.Aggregate((e1, e2) => <[ $e1 && $e2 ]>);


<[ if ($check < text.Length && $condExpr) pos + $(len : int) else -1 ]> <[
if ($check < text.Length && $condExpr)
pos + $(len : int)
else
{
$(SetParsingErrorCode(rule.str));
-1
}
]>
} }
else else
<[ pos ]> <[ pos ]>
Expand Down
Expand Up @@ -45,8 +45,7 @@ namespace Nemerle.Parser
$(names.Result : dyn) = result; $(names.Result : dyn) = result;
} }
else else
when (_parsingErrors.$(_grammarCompiller.DecorateRuleName(rd) : dyn) < pos) $(SetParsingErrorCode($"#$(rd.Name)"));
_parsingErrors.$(_grammarCompiller.DecorateRuleName(rd) : dyn) = pos;


newPos newPos
} }
Expand Down
36 changes: 36 additions & 0 deletions Nemerle.Parser.Macro/Compiler/RuleCompiler/SetParsingErrorCode.n
@@ -0,0 +1,36 @@
using Nemerle.Collections;
using Nemerle.Text;
using Nemerle.Utility;
using Nemerle.Compiler;
using Nemerle.Compiler.Parsetree;
using Nemerle.Compiler.Typedtree;

using System;
using System.Linq;
using SCG = System.Collections.Generic;

namespace Nemerle.Parser
{
partial internal class RuleCompiler
{
public SetParsingErrorCode(name : string) : PExpr
{
def isSimple = _ruleDefinition is RuleDefinition.Simple;
def (posName, tokenName) = if (isSimple)
( <[ _parsingErrors.$(_grammarCompiller.DecorateRuleName(_ruleDefinition) : dyn) ]>
, <[ _parsingErrors.$(_grammarCompiller.DecorateTokenDescriptor(_ruleDefinition) : dyn) ]>
)
else
( <[ _grammar._parsingErrors.$(_grammarCompiller.DecorateRuleName(_ruleDefinition) : dyn) ]>
, <[ _grammar._parsingErrors.$(_grammarCompiller.DecorateTokenDescriptor(_ruleDefinition) : dyn) ]>
);
<[
when ($posName < pos)
{
$posName = pos;
$tokenName = $(_grammarCompiller.GetTokenDescriptor(name, _ruleDefinition));
}
]>
}
}
}
3 changes: 3 additions & 0 deletions Nemerle.Parser.Macro/Nemerle.Parser.Macro-VS_2010.nproj
Expand Up @@ -254,6 +254,9 @@
<Compile Include="Compiler\RuleCompiler\MakeHandlerCall.n"> <Compile Include="Compiler\RuleCompiler\MakeHandlerCall.n">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Compiler\RuleCompiler\SetParsingErrorCode.n">
<SubType>Code</SubType>
</Compile>
<Compile Include="Compiler\RuleCompiler\TestCharConditionCode.n"> <Compile Include="Compiler\RuleCompiler\TestCharConditionCode.n">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
Expand Down
18 changes: 18 additions & 0 deletions Nemerle.Parser/Descriptors/TokenDescriptor.n
@@ -0,0 +1,18 @@
using Nemerle;
using Nemerle.Collections;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.Collections.Generic;
using System.Linq;

namespace Nemerle.Parser
{
[Record]
public class TokenDescriptor
{
public Rule : RuleDescriptor { get; }
public Name : string { get; }
}
}
2 changes: 1 addition & 1 deletion Nemerle.Parser/Internal/Parser.n
Expand Up @@ -60,7 +60,7 @@ namespace Nemerle.Parser.Internal
} }
} }


public GetErrors() : int * SCG.List[RuleDescriptor] public GetErrors() : int * SCG.List[TokenDescriptor]
{ {
mutable pos = -1; mutable pos = -1;
def rules = SCG.List(); def rules = SCG.List();
Expand Down
2 changes: 1 addition & 1 deletion Nemerle.Parser/Internal/ParsingErrors.n
Expand Up @@ -11,7 +11,7 @@ namespace Nemerle.Parser.Internal
{ {
public abstract class ParsingErrors public abstract class ParsingErrors
{ {
public abstract GetErrors(pos : ref int, descriptors : SCG.List[RuleDescriptor]) : void; public abstract GetErrors(pos : ref int, descriptors : SCG.List[TokenDescriptor]) : void;
public abstract Clear() : void; public abstract Clear() : void;
} }
} }
3 changes: 3 additions & 0 deletions Nemerle.Parser/Nemerle.Parser-VS_2010.nproj
Expand Up @@ -67,6 +67,9 @@
<Compile Include="Descriptors\RuleDescriptor.n"> <Compile Include="Descriptors\RuleDescriptor.n">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Descriptors\TokenDescriptor.n">
<SubType>Code</SubType>
</Compile>
<Compile Include="GrammarsAttribute.n"> <Compile Include="GrammarsAttribute.n">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
Expand Down
8 changes: 5 additions & 3 deletions Test/Main.n
Expand Up @@ -76,9 +76,11 @@ module Program
{ {
| None => | None =>
WriteLine($"Fail: \"$text\""); WriteLine($"Fail: \"$text\"");
def (pos, rules) = parser.Parser.GetErrors(); def (pos, tokens) = parser.Parser.GetErrors();
foreach (rule in rules) def (line, pos) = parser.ParsingSource.PositionToLineColumn(pos);
WriteLine($" $pos $(rule.Grammar.Name).$(rule.Name)"); foreach (token in tokens)
WriteLine($" $line:$pos expected \"$(token.Name)\" in rule $(token.Rule.Grammar.Name).$(token.Rule.Name)");

| Some(ast) => | Some(ast) =>
def printAst(ast : ExprAst) def printAst(ast : ExprAst)
{ {
Expand Down

0 comments on commit 2b1312f

Please sign in to comment.