-
-
Save fowlmouth/57405bf26ed8c1b4e357 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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