# The current state
# Used by generated parsers
- var state: LRState
+ var state: LRState is noinit
init
do
# 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
# 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(" ")
var line_end: Int
var col_start: Int
var col_end: Int
+
redef fun to_s do return "{line_start}:{col_start}-{line_end}:{col_end}"
+
+ # Get the lines covered by `self` and underline the target columns.
+ #
+ # This is useful for pretty printing errors or debug the output
+ #
+ # ~~~
+ # var src = "var Foo = new Array[Int]"
+ # var pos = new Position(0,0, 1, 1, 5, 8)
+ #
+ # assert pos.underline(src) == """
+ # var Foo = new Array[Int]
+ # ^^^"""
+ # ~~~
+ fun underline(source: Text): String
+ do
+ var res = new FlatBuffer
+
+ # All the concerned lines
+ var lines = source.split("\n")
+ for line in [line_start..line_end] do
+ res.append lines[line-1]
+ res.append "\n"
+ end
+
+ # Cover all columns, no matter their lines
+ var col_start = col_start.min(col_end)
+ var col_end = self.col_start.max(col_end)
+
+ # " ^^^^"
+ var ptr = " "*(col_start-1).max(0) + "^"*(col_end-col_start)
+ res.append ptr
+
+ return res.to_s
+ end
end
# A node of a syntactic tree
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")
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
private class DephIterator
super Iterator[Node]
+
var stack = new List[Iterator[nullable Node]]
- init(i: Iterator[nullable Node])
- do
+ init(i: Iterator[nullable Node]) is old_style_init do
stack.add i
end
end
# The text associated with the token
- var text: String writable = ""
+ var text: String = "" is writable
redef fun to_s do
var res = super
# 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
# A hogeneous sequence of node, used to represent unbounded lists (and + modifier)
class Nodes[T: Node]
super Node
- redef var children = new Array[T]
+ redef var children: Array[T] = new Array[T]
end
# A production with a specific, named and statically typed children
-class NProd
+abstract class NProd
super Node
redef var children: SequenceRead[nullable Node] = new NProdChildren(self)
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"
end
text = args.shift
else
- var f = new IFStream.open(filepath)
+ var f = new FileReader.open(filepath)
text = f.read_all
f.close
end
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
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