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
Original file line number Diff line number Diff line change
Expand Up @@ -166,25 +166,43 @@ module Program
match (parser.ParseStart(code))
{
| None =>
WriteLine($"Fail: \"$code\"");
def (pos, rules) = parser.Parser.GetErrors();
WriteLine($"Fail:\n\"$code\"");
def (pos, tokens) = parser.Parser.GetErrors();
def (line, pos) = parser.ParsingSource.PositionToLineColumn(pos);
foreach (rule in rules)
WriteLine($" $line:$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) =>
//WriteLine($"Ok: \"$code\" AST: $(printAst(ast))");
_ = ast;
WriteLine("OK");
WriteLine($"OK:\n\"$code\"");
}
WriteLine();
}

test(<#
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;
type X = A.B;
}
#>);
_ = ReadLine();
_ = ReadKey();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ namespace Nemerle.Parser
{
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
{
foreach (rd in ParsedGrammar.Rules)
Expand All @@ -31,6 +39,9 @@ namespace Nemerle.Parser
}
]>;
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))
{
| RuleType.NType(type) => tb.Define(<[decl: public ResultType() : $(type : typed) { mutable res; res } ]>)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,20 @@ namespace Nemerle.Parser
{
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 name = DecorateRuleName(rd);
Expand All @@ -27,13 +40,13 @@ namespace Nemerle.Parser
descriptors.Clear();
}
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:
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;
_ = descriptors;
Expand All @@ -49,7 +62,10 @@ namespace Nemerle.Parser
]>);

foreach (rd in rules)
{
_ = 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
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ namespace Nemerle.Parser
DecorateRuleName(rd.Name)
}

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

public DecorateRuleClassName(rd : RuleDefinition) : string
{
match (rd)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ namespace Nemerle.Parser
if (newPos > 0)
$setResult;
else
when (_grammar._parsingErrors.$(_grammarCompiller.DecorateRuleName(rd) : dyn) < pos)
_grammar._parsingErrors.$(_grammarCompiller.DecorateRuleName(rd) : dyn) = pos;
$(SetParsingErrorCode($"#$(rd.Name)"));
newPos;
]>)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ namespace Nemerle.Parser
if (newPos > 0)
$setResult;
else
when (_grammar._parsingErrors.$(_grammarCompiller.DecorateRuleName(rd) : dyn) < pos)
_grammar._parsingErrors.$(_grammarCompiller.DecorateRuleName(rd) : dyn) = pos;
$(SetParsingErrorCode($"#$(rd.Name)"));
newPos
]>)
}
Expand Down
10 changes: 9 additions & 1 deletion Nemerle.Parser.Macro/Compiler/RuleCompiler/CompileRuleString.n
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,15 @@ namespace Nemerle.Parser
def exprs = rule.str.Select(makeCharCheckCode);
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
<[ pos ]>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ namespace Nemerle.Parser
$(names.Result : dyn) = result;
}
else
when (_parsingErrors.$(_grammarCompiller.DecorateRuleName(rd) : dyn) < pos)
_parsingErrors.$(_grammarCompiller.DecorateRuleName(rd) : dyn) = pos;
$(SetParsingErrorCode($"#$(rd.Name)"));

newPos
}
Expand Down
36 changes: 36 additions & 0 deletions Nemerle.Parser.Macro/Compiler/RuleCompiler/SetParsingErrorCode.n
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,9 @@
<Compile Include="Compiler\RuleCompiler\MakeHandlerCall.n">
<SubType>Code</SubType>
</Compile>
<Compile Include="Compiler\RuleCompiler\SetParsingErrorCode.n">
<SubType>Code</SubType>
</Compile>
<Compile Include="Compiler\RuleCompiler\TestCharConditionCode.n">
<SubType>Code</SubType>
</Compile>
Expand Down
18 changes: 18 additions & 0 deletions Nemerle.Parser/Descriptors/TokenDescriptor.n
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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;
def rules = SCG.List();
Expand Down
2 changes: 1 addition & 1 deletion Nemerle.Parser/Internal/ParsingErrors.n
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Nemerle.Parser.Internal
{
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;
}
}
3 changes: 3 additions & 0 deletions Nemerle.Parser/Nemerle.Parser-VS_2010.nproj
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@
<Compile Include="Descriptors\RuleDescriptor.n">
<SubType>Code</SubType>
</Compile>
<Compile Include="Descriptors\TokenDescriptor.n">
<SubType>Code</SubType>
</Compile>
<Compile Include="GrammarsAttribute.n">
<SubType>Code</SubType>
</Compile>
Expand Down
8 changes: 5 additions & 3 deletions Test/Main.n
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,11 @@ module Program
{
| None =>
WriteLine($"Fail: \"$text\"");
def (pos, rules) = parser.Parser.GetErrors();
foreach (rule in rules)
WriteLine($" $pos $(rule.Grammar.Name).$(rule.Name)");
def (pos, tokens) = parser.Parser.GetErrors();
def (line, pos) = parser.ParsingSource.PositionToLineColumn(pos);
foreach (token in tokens)
WriteLine($" $line:$pos expected \"$(token.Name)\" in rule $(token.Rule.Grammar.Name).$(token.Rule.Name)");

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

0 comments on commit 2b1312f

Please sign in to comment.