Permalink
Browse files

Provide some useful errors in the metagrammar.

  • Loading branch information...
1 parent c595ce7 commit ec39f61d6e0299aeb7703d6cbbab981f63417343 @seancribbs committed Jun 27, 2009
Showing with 47 additions and 1 deletion.
  1. +1 −1 src/peg_gen.erl
  2. +46 −0 src/peg_meta_gen.erl
View
2 src/peg_gen.erl
@@ -59,7 +59,7 @@ create_transform(false,_) ->
create_transform(ModName,Dir) when is_atom(ModName) ->
XfFile = filename:join(Dir, atom_to_list(ModName) ++ ".erl"),
case filelib:is_regular(XfFile) of
- true -> io:format("~p already exists, skipping generation.", [XfFile]);
+ true -> io:format("'~s' already exists, skipping generation.~n", [XfFile]);
false -> generate_transform_stub(XfFile, ModName)
end,
["transform(Symbol,Node) -> ",atom_to_list(ModName),":transform(Symbol, Node)."].
View
46 src/peg_meta_gen.erl
@@ -3,13 +3,15 @@
-author("Sean Cribbs <seancribbs@gmail.com>").
transform(rules, Node) ->
+ verify_rules(),
Rules = string:join(lists:nth(2, Node), ";\n\n"),
Rules ++ ".\n";
transform(declaration_sequence, Node) ->
FirstRule = proplists:get_value(head, Node),
OtherRules = [lists:last(I) || I <- proplists:get_value(tail, Node, [])],
[FirstRule|OtherRules];
transform(declaration, [{nonterminal,Symbol}|Node]) ->
+ add_lhs(Symbol),
"rule("++Symbol++") ->\n " ++ lists:nth(4, Node);
transform(sequence, Node) ->
Tail = [lists:nth(2, S) || S <- proplists:get_value(tail, Node)],
@@ -36,6 +38,7 @@ transform(character_class, Node) ->
transform(parenthesized_expression, Node) ->
lists:nth(3, Node);
transform(atomic, {nonterminal, Symbol}) ->
+ add_nt(Symbol),
"fun " ++ Symbol ++ "/2";
transform(primary, [Atomic, one_or_more]) ->
"peg:one_or_more("++Atomic++")";
@@ -68,3 +71,46 @@ transform(Rule, Node) when is_atom(Rule) ->
escape_quotes(String) ->
{ok, RE} = re:compile("\""),
re:replace(String, RE, "\\\\\"", [global, {return, list}]).
+
+add_lhs(Symbol) ->
+ case get(lhs) of
+ undefined ->
+ put(lhs, [Symbol]);
+ L when is_list(L) ->
+ put(lhs, [Symbol|L])
+ end.
+
+add_nt(Symbol) ->
+ case get(nts) of
+ undefined ->
+ put(nts, [Symbol]);
+ L when is_list(L) ->
+ case lists:member(Symbol, L) of
+ true ->
+ ok;
+ _ ->
+ put(nts, [Symbol|L])
+ end
+ end.
+
+verify_rules() ->
+ LHS = erase(lhs),
+ NTs = erase(nts),
+ NonRoots = tl(lists:reverse(LHS)),
+ lists:foreach(fun(L) ->
+ case lists:member(L, NTs) of
+ true ->
+ ok;
+ _ ->
+ io:format("neotoma warning: rule '~s' is unused.~n", [L])
+ end
+ end, NonRoots),
+ lists:foreach(fun(S) ->
+ case lists:member(S, LHS) of
+ true ->
+ ok;
+ _ ->
+ io:format("neotoma error: symbol '~s' has no reduction. No parser will be generated!~n", [S]),
+ exit({neotoma, {no_reduction, list_to_atom(S)}})
+ end
+ end, NTs).

0 comments on commit ec39f61

Please sign in to comment.