X-Git-Url: http://nitlanguage.org diff --git a/lib/nitcc_runtime.nit b/lib/nitcc_runtime.nit index 20342e6..923ef18 100644 --- a/lib/nitcc_runtime.nit +++ b/lib/nitcc_runtime.nit @@ -76,6 +76,7 @@ abstract class Parser #print " expected: {state.error_msg}" #print " node_stack={node_stack.join(", ")}" #print " state_stack={state_stack.join(", ")}" + node_stack.add(token) var error: NError if token isa NLexerError then error = token @@ -85,7 +86,7 @@ abstract class Parser error.text = token.text error.token = token end - error.error_tree.items.add_all(node_stack) + error.error_tree.children.add_all(node_stack) error.expected = state.error_msg node_stack.clear node_stack.add error @@ -98,7 +99,7 @@ abstract class Parser # The current state # Used by generated parsers - var state: LRState + var state: LRState is noinit init do @@ -115,7 +116,7 @@ abstract class Parser # Should the parser stop # Used by generated parsers - var stop writable = true + var stop = true is writable # Parse a full sequence of tokens and return a complete syntactic tree fun parse: Node @@ -185,12 +186,14 @@ abstract class Lexer last_state = state end var c + var next if pos >= length then c = '\0' + next = null else - c = text[pos] + c = text.chars[pos] + next = state.trans(c) end - var next = state.trans(c) if next == null then if pos_start < length then if last_state == null then @@ -271,9 +274,8 @@ end # Print a node (using to_s) on a line and recustively each children indented (with two spaces) class TreePrinterVisitor super Visitor - var writer: OStream + var writer: Writer private var indent = 0 - init(writer: OStream) do self.writer = writer redef fun visit(n) do for i in [0..indent[ do writer.write(" ") @@ -302,9 +304,12 @@ abstract class Node # The name of the node (as used in the grammar file) fun node_name: String do return class_name - # A point of view on the direct childrens of the node + # A point of view on the direct children of the node fun children: SequenceRead[nullable Node] is abstract + # A point of view of a depth-first visit of all non-null children + var depth: Collection[Node] = new DephCollection(self) + # Visit all the children of the node with the visitor `v` protected fun visit_children(v: Visitor) do @@ -312,12 +317,12 @@ abstract class Node end # The position of the node in the input stream - var position: nullable Position writable = null + var position: nullable Position = null is writable # Produce a graphiz file for the syntaxtic tree rooted at `self`. fun to_dot(filepath: String) do - var f = new OFStream.open(filepath) + var f = new FileWriter.open(filepath) f.write("digraph g \{\n") f.write("rankdir=BT;\n") @@ -341,7 +346,7 @@ abstract class Node f.close end - private fun to_dot_visitor(f: OStream, a: Array[NToken]) + private fun to_dot_visitor(f: Writer, a: Array[NToken]) do f.write("n{object_id} [label=\"{node_name}\"];\n") for x in children do @@ -361,6 +366,42 @@ abstract class Node end end +private class DephCollection + super Collection[Node] + var node: Node + redef fun iterator do return new DephIterator([node].iterator) +end + +private class DephIterator + super Iterator[Node] + + var stack = new List[Iterator[nullable Node]] + + init(i: Iterator[nullable Node]) is old_style_init do + stack.add i + end + + redef fun is_ok do return not stack.is_empty + redef fun item do return stack.last.item.as(not null) + redef fun next + do + var i = stack.last + stack.push i.item.children.iterator + i.next + while is_ok do + if not stack.last.is_ok then + stack.pop + continue + end + if stack.last.item == null then + stack.last.next + continue + end + return + end + end +end + # A token produced by the lexer and used in a syntactic tree abstract class NToken super Node @@ -381,7 +422,7 @@ abstract class NToken end # The text associated with the token - var text: String writable = "" + var text: String = "" is writable redef fun to_s do var res = super @@ -425,26 +466,34 @@ end class NLexerError super NError - redef fun unexpected do return "character '{text.first}'" + redef fun unexpected do return "character '{text.chars.first}'" end # A parser error linked to a unexpected token class NParserError super NError + # The unexpected token - var token: nullable NToken + var token: nullable NToken = null - redef fun unexpected do return token.node_name + redef fun unexpected + do + var res = token.node_name + var text = token.text + if not text.is_empty and res != "'{text}'" then + res += " '{text.escape_to_c}'" + end + return res + end end # A hogeneous sequence of node, used to represent unbounded lists (and + modifier) class Nodes[T: Node] super Node - redef fun children do return items - var items = new Array[T] + redef var children: Array[T] = new Array[T] end -# A production with a specific, named and statically typed childrens +# A production with a specific, named and statically typed children class NProd super Node redef var children: SequenceRead[nullable Node] = new NProdChildren(self) @@ -501,7 +550,7 @@ abstract class TestParser var filepath = args.shift var text if filepath == "-" then - text = stdin.read_all + text = sys.stdin.read_all else if filepath == "-e" then if args.is_empty then print "Error: -e need a text" @@ -509,7 +558,7 @@ abstract class TestParser end text = args.shift else - var f = new IFStream.open(filepath) + var f = new FileReader.open(filepath) text = f.read_all f.close end @@ -533,7 +582,7 @@ abstract class TestParser var tokout = "{name}.tokens.out" print "TOKEN: {tokens.length} tokens (see {tokout})" - var f = new OFStream.open(tokout) + var f = new FileWriter.open(tokout) for t in tokens do f.write "{t.to_s}\n" end @@ -545,7 +594,7 @@ abstract class TestParser var n = p.parse var astout = "{name}.ast.out" - f = new OFStream.open(astout) + f = new FileWriter.open(astout) var tpv = new TreePrinterVisitor(f) var astdotout = "{name}.ast.dot" if n isa NError then @@ -554,7 +603,7 @@ abstract class TestParser tpv.enter_visit(n) n = n.error_tree else - print "ROOT: {n} (see {astout} and {astdotout})" + print "ROOT: {n}; {n.depth.length} nodes (see {astout} and {astdotout})" end tpv.enter_visit(n) n.to_dot(astdotout)