Skip to content

Instantly share code, notes, and snippets.

@fowlmouth
Created November 20, 2013 11:33
Show Gist options
  • Save fowlmouth/57405bf26ed8c1b4e357 to your computer and use it in GitHub Desktop.
Save fowlmouth/57405bf26ed8c1b4e357 to your computer and use it in GitHub Desktop.
import
strutils, fowltek/parsetools/g_lex, fowltek/parsetools/g_parse
const
keywords = ["var", "func", "type"]
tkKeyword = tkUser1
type
PNode* = ref object{.inheritable.}
PIdentNode* = ref object of PNode
ident*: string
PIntNode* = ref object of PNode
ival*: int
PFloatNode* = ref object of PNode
fval*: int
PStringNode* = ref object of PNode
sval*: string
TTypeModifierKind* = enum
TypePointer, TypeReference,
TypeSizedArray, TypeArray,
TypeConst, TypeStatic
TTypeModifier* = object
case kind*: TTypeModifierKind
of TypeSizedArray:
size*: PNode
else: nil
PTypeNode* = ref object of PNode
base*: PNode
modifiers*: seq[TTypeModifier]
PVarDeclNode* = ref object of PNode
typ*: PTypeNode
name*: PIdentNode
PNodeOfNodes* = ref object of PNode
children*: seq[PNode]
PStmtList* = ref object of PNodeOfNodes
type
PParser = var TParser[PNode]
proc parseTopLevelStatement (P: PParser): PNode
proc parse (input: string): PNode =
var parser = newParser(parseTopLevelStatement)
parser.lex.add_postHook do(L: var TLexer; tok: var TToken)->bool:
if tok.kind == tkIdent and tok.sval.tolower in keywords:
tok.kind = tkKeyword
tok.sval = tok.sval.toLower
result = true
parser.parse input
proc parseType (P: PParser): PTypeNode =
result = PTypeNode(modifiers: @[])
block typeBuilding:
while true:
case P.currentTok.kind
of tkOperator:
case P.currentTok.sval
of "*", "^":
P.consumeTok
result.modifiers.add TTypeModifier(kind: TypePointer)
of "&":
P.consumeTok
result.modifiers.add TTypeModifier(kind: TypeReference)
of tkBracketOpen:
P.consumeTok
if P.currentTok.kind == tkBracketClose:
result.modifiers.add TTypeModifier(kind: TypeArray)
else:
#result.modifiers.add TTypeModifier(
# kind: TypeSizedArray,
# size: P.parseExpr)
of tkIdent:
let S = P.currentTok.sval.toLower
case S
of "const":
result.modifiers.add TTypeModifier(kind: TypeConst)
of "static":
result.modifiers.add TTypeModifier(kind: TypeStatic)
of "struct", "enum", "unsigned", "signed":
result.base = PStringNode(sval: S & " " & p.consumeStrTok.sval)
break typeBuilding
else:
result.base = PStringNode(sval: S)
break typeBuilding
else:
echo "Ignored! ", P.consumeTok
proc parseVarDecl (P: PParser): PVarDeclNode =
P.consumeStrTok([], "var")
result = PVarDeclNode(name: PIdentNode(ident: P.consumeStrTok.sval))
#P.expectStrTok([tkOperator, tkIdent], [":", "is"])
#P.consumeTok
P.consumeTok tkColon
result.typ = P.parseType
proc parseFuncDecl (P: PParser): PNode = nil
proc parseTopLevelStatement (P: PParser): PNode =
P.expectTok tkKeyword
case P.currentTok.sval
of "var":
return P.parseVarDecl
of "func":
return P.parseFuncDecl
else:
P.consumeTOK()
nil
type
PRenderState = var TRenderState
TRenderState = object
indentation: int
proc `$` (some: PNode): string = repr(some)
method render* (N: PNode; S: PRenderState): string = $N
method render* (N: PStmtList; S: PRenderState): string =
result = ""
for C in N.children:
result.add C.render(S)
proc render* (N: PNode): string =
var S: TRenderState
N.render S
when isMainModule:
const TestString = """
var x: int
func main: (void) -> int {
return 0
}
"""
discard """
output:
int x;
int main(void) {
return 0;
}
"""
TestString.parse.render.echo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment