Skip to content

Commit

Permalink
NitCC use ASTType to represent AST information #2855 from privat/nitc…
Browse files Browse the repository at this point in the history
…c_asttype
  • Loading branch information
privat authored Aug 29, 2024
2 parents 2fcb457 + beea28f commit 17eaca0
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 81 deletions.
2 changes: 1 addition & 1 deletion contrib/nitcc/src/autom.nit
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,7 @@ private class DFAGenerator
add("\t\tvar t = new MyNToken\n")
add("\t\tt.text = position.extract(source)\n")
else
add("\t\tvar t = new {token.acname}\n")
add("\t\tvar t = new {token.ast_type.to_nit}\n")
var ttext = token.text
if ttext == null then
add("\t\tt.text = position.extract(source)\n")
Expand Down
127 changes: 90 additions & 37 deletions contrib/nitcc/src/grammar.nit
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ class Gram
do
var res = new FlatBuffer
for p in prods do
if p.spe != null then
res.append("{p.name} \{-> {p.spe.name}\}=\n")
if not p.is_ast then
res.append("{p.name} \{-> {p.ast_type}\}=\n")
else
res.append("{p.name} =\n")
end
Expand Down Expand Up @@ -339,12 +339,14 @@ class Gram
var cname = "_plus{plusizes.length}"
var prod = new Production("{e}+")
prod.cname = cname
prod.acname = "Nodes[{e.acname}]"
prod.ast_type = e.ast_type.as_array
prods.add(prod)
var alt1 = prod.new_alt("{cname}_one", e)
alt1.trans = true
alt1.codes = [new CodeNewNodes(alt1), new CodeGet(0), new CodeAdd: Code]
var alt2 = prod.new_alt("{cname}_more", prod, e)
alt2.codes = [new CodeGet(0), new CodeGet(1), new CodeAdd: Code]
alt2.trans = true
plusizes[e] = prod
return prod
end
Expand All @@ -370,12 +372,14 @@ class Gram
var cname = "_opt{quesizes.length}"
var prod = new Production("{e}?")
prod.cname = cname
prod.acname = "nullable {e.acname}"
prod.ast_type = e.ast_type.as_nullable
prods.add(prod)
var a1 = prod.new_alt("{cname}_one", e)
a1.trans = true
a1.codes = [new CodeGet(0)]
var a0 = prod.new_alt0("{cname}_none")
a0.codes = [new CodeNull]
a0.trans = true
quesizes[e] = prod
return prod
end
Expand Down Expand Up @@ -409,9 +413,9 @@ class Gram

for t in tokens do
if t.name == "Eof" then
g.add "redef class {t.acname}"
g.add "redef class NEof"
else
g.add "class {t.acname}"
g.add "class {t.ast_type.to_nit}"
g.add "\tsuper NToken"
end
g.add "\tredef fun node_name do return \"{t.name.escape_to_nit}\""
Expand All @@ -421,10 +425,9 @@ class Gram
var ps = prods.to_a
ps.add_all(ast_prods)
for p in ps do
if p.spe == null and not p.altone then
if p.name.has_suffix("?") or p.name.has_suffix("+") then continue
if p.is_ast and not p.altone then
g.add "# Production {p}"
g.add "class {p.acname}"
g.add "class {p.ast_type.to_nit}"
g.add "\tsuper NProd"
g.add "\tredef fun node_name do return \"{p.name.escape_to_nit}\""
g.add "end"
Expand All @@ -439,14 +442,16 @@ class Gram
if p.altone then
g.add "\tsuper NProd"
else
g.add "\tsuper {p.acname}"
g.add "\tsuper {p.ast_type.to_nit}"
end
g.add "\tredef fun node_name do return \"{a.name.escape_to_nit}\""
var initarg = new Array[String]
for i in [0..a.elems.length[ do
g.add "\t# Children {i}: {a.elems[i]}"
g.add "\tvar n_{a.elemname(i)}: {a.elems[i].acname}"
initarg.add("n_{a.elemname(i)}: {a.elems[i].acname}")
var t = a.elems[i].ast_type.to_nit
var n = a.elemname(i)
g.add "\tvar n_{n}: {t}"
initarg.add("n_{n}: {t}")
end
g.add "\tredef fun number_of_children do return {a.elems.length}"
g.add "\tredef fun child(i) do"
Expand Down Expand Up @@ -474,21 +479,24 @@ class Production
# Is self the accept production
var accept = false

# Is self transformed to a other production for the AST
# FIXME: cleanup AST
var spe: nullable Production = null is writable
# Is self present as a distinct AST class
fun is_ast: Bool do return parent_production == self

# The production AST where non transformed alternative are attached to.
# If no such production exists, return null
fun parent_production: nullable Production
do
var res = ast_type.element
if not res isa Production then return null # it is a token
if ast_type.is_plain then return res
return null # is is nullable and/or array
end


# Is self contains only a single alternative (then no need for a abstract production class in the AST)
# FIXME cleanup AST
var altone = false is writable

# The cname of the class in the AST
# FIXME: cleanup AST
redef fun acname do
if spe != null then return spe.acname
return super
end

# Is the production nullable
var is_nullable = false

Expand Down Expand Up @@ -553,6 +561,64 @@ class Production
end
end

# static types of AST elements (AST productions and tokens)
class ASTType
var element: Element
var is_nullable: Bool = false
var is_array: Bool = false

fun is_plain: Bool
do
return not is_nullable and not is_array
end

redef fun to_s
do
var res = element.name
if is_nullable then
if is_array then
return "{res}*"
else
return "{res}?"
end
else
if is_array then
return "{res}+"
else
return res
end
end
end

fun as_nullable: ASTType
do
if is_nullable then return self
var res = new ASTType(element)
res.is_nullable = true
res.is_array = is_array
return res
end
fun as_array: ASTType
do
if is_array then return self
var res = new ASTType(element)
res.is_nullable = is_nullable
res.is_array = true
return res
end
fun to_nit: String
do
var res = "N" + element.cname
if is_array then
res = "Nodes[{res}]"
end
if is_nullable then
res = "nullable {res}"
end
return res
end
end

# An alternative of a production
class Alternative
# The production
Expand Down Expand Up @@ -664,31 +730,18 @@ abstract class Element
var name: String
redef fun to_s do return name

var ast_type: ASTType = new ASTType(self) is writable

# An example of a string
fun sample_to_s: String is abstract

private var acname_cache: nullable String = null

# The mangled name of the element
var cname: String is noinit, writable

init
do
cname = name
end

# The name of the class in the AST
fun acname: String do
var res = acname_cache
if res == null then
res = "N{cname}"
acname_cache = res
end
return res
end

# The name of the class in the AST
fun acname=(s: String) do acname_cache = s
end

# A terminal element
Expand Down
6 changes: 3 additions & 3 deletions contrib/nitcc/src/lrautomaton.nit
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ redef class Generator
add "end"

for t in gram.tokens do
add "redef class {t.acname}"
add "redef class {t.ast_type.to_nit}"
for s in t.shifts do
if not s.need_guard then continue
add "\tredef fun action_s{s.number}(parser) do"
Expand Down Expand Up @@ -484,7 +484,7 @@ redef class Generator
add "\t\t# REDUCE {alt}"
var i = alt.elems.length - 1
for e in alt.elems.to_a.reversed do
add "\t\tvar n{i} = parser.pop.as({e.acname})"
add "\t\tvar n{i} = parser.pop.as({e.ast_type.to_nit})"
i -= 1
end

Expand Down Expand Up @@ -520,7 +520,7 @@ redef class Generator
st.add("p{cpt}")
else if c isa CodeNewNodes then
cpt += 1
add "\t\tvar p{cpt} = new {c.alt.prod.acname}"
add "\t\tvar p{cpt} = new {c.alt.prod.ast_type.to_nit}"
st.add("p{cpt}")
else if c isa CodeAdd then
var a1 = st.pop
Expand Down
Loading

0 comments on commit 17eaca0

Please sign in to comment.