From 3395cd7dc356b61fe48ee9d755eef8a7b19ee9f1 Mon Sep 17 00:00:00 2001 From: Kyle Gunger Date: Fri, 29 Oct 2021 20:06:51 -0400 Subject: [AST] Statement parsing (incomplete) Still need to figure out a check for a type followed by a value --- qualifiers.txt | 2 +- small-tests/base.tnsl | 3 +- small-tests/examp.tnsl | 4 +- src/tparse/tree-statement.go | 146 ++++++++++++++++++++++++++++++++----------- src/tparse/tree-value.go | 13 ++-- tests/block-test.tnsl | 74 +++++++++++----------- tests/literal-test.tnsl | 7 ++- tests/parameter-test.tnsl | 2 +- 8 files changed, 165 insertions(+), 86 deletions(-) diff --git a/qualifiers.txt b/qualifiers.txt index 835a5f5..18c447f 100644 --- a/qualifiers.txt +++ b/qualifiers.txt @@ -22,7 +22,6 @@ structure of blocks: (block start) interface (defword) - enum (defword) (return type list) loop (bool params) (loop rets) if (bool params) @@ -60,6 +59,7 @@ keyword statements: delete (list of defwords)* struct (defword) (struct params)* +enum (defword) (return type list) (enum values) continue break label (defword) diff --git a/small-tests/base.tnsl b/small-tests/base.tnsl index f291cf3..157b65b 100644 --- a/small-tests/base.tnsl +++ b/small-tests/base.tnsl @@ -2,4 +2,5 @@ ;a.pl() # Same -; a . pl () \ No newline at end of file +; a . pl () + diff --git a/small-tests/examp.tnsl b/small-tests/examp.tnsl index 196db40..f8579a0 100644 --- a/small-tests/examp.tnsl +++ b/small-tests/examp.tnsl @@ -19,7 +19,7 @@ # pass a variable ;int s = 3 -;byte bitbyte = .2 +;int8 bitbyte = .2 # generic scope block @@ -120,7 +120,7 @@ ;/ -/; switch (i) +/; match (i) # You can do stuff here as well ;int t = 0 diff --git a/src/tparse/tree-statement.go b/src/tparse/tree-statement.go index 167cee2..bb8bde2 100644 --- a/src/tparse/tree-statement.go +++ b/src/tparse/tree-statement.go @@ -17,32 +17,48 @@ package tparse func parseBlock(tokens *[]Token, tok, max int) (Node, int) { - out := Node{} + out, tmp, def, name := Node{}, Node{}, Node{}, false out.Data = Token{Type: 10, Data: "block"} - var tmp Node + def.Data = Token{Type: 10, Data: "blockdef"} tok++ - def := Node{} - def.Data = Token{Type: 10, Data: "blockdef"} - for ;tok < max; tok++{ t := (*tokens)[tok] - + tmp = Node{} switch t.Type { case DELIMIT: if t.Data == "(" { - tmp, tok = parseParamList(tokens, tok, max) - def.Sub = append(out.Sub, tmp) + tmp, tok = parseValueList(tokens, tok, max) + def.Sub = append(def.Sub, tmp) } else if t.Data == "[" { tmp, tok = parseTypeList(tokens, tok, max) - def.Sub = append(out.Sub, tmp) + def.Sub = append(def.Sub, tmp) } else { goto BREAK } case DEFWORD: - + if name { + errOut("Unexpected defword, the block has already been given a name or keyword.", t) + } + tmp.Data = t + def.Sub = append(def.Sub, tmp) + name = true case KEYWORD: + if name { + errOut("Unexpected keyword, the block has already been given a name or keyword.", t) + } + switch t.Data { + case "else": + if (*tokens)[tok+1].Data == "if" { + tmp.Data = Token{KEYWORD, "elif", t.Line, t.Char} + tok++ + name = true + continue + } + case "if", "match", "case", "loop": + case "export", "inline", "raw", "override": + } case LINESEP: goto BREAK } @@ -86,49 +102,103 @@ func parseStatement(tokens *[]Token, tok, max int) (Node, int) { out.Data = Token{Type: 11, Data: ";"} var tmp Node - tok++ - - for ; tok < max; tok++ { - t := (*tokens)[tok] - - switch t.Type { - case LINESEP, DELIMIT: - return out, tok - case INLNSEP: - tok++ - default: - errOut("Error: unexpected token when parsing a list of types", t) + // Check for keyword, definition, then if none of those apply, assume it's a value. + if (*tokens)[tok].Type == KEYWORD { + tmp, tok = keywordStatement(tokens, tok, max) + out.Sub = append(out.Sub, tmp) + } else { + // do check for definition + if false { + // if not, parse a value + tmp, tok = parseDefinition(tokens, tok, max) + } else { + // if not, parse a value + tmp, tok = parseValue(tokens, tok, max) } - - tmp, tok = parseType(tokens, tok, max, true) out.Sub = append(out.Sub, tmp) } return out, tok } -func parseDef(tokens *[]Token, tok, max int) (Node, int) { +// Works? Please test. +func keywordStatement(tokens *[]Token, tok, max int) (Node, int) { out := Node{} - out.Data = Token{Type: 10, Data: "list"} + out.Data = (*tokens)[tok] + out.IsBlock = false var tmp Node + tmp.IsBlock = false - tok++ + if tok + 1 < max { + tok++ + } else { + return out, max + } - for ; tok < max; tok++ { - t := (*tokens)[tok] + switch out.Data.Data { + case "raw": + // Something, something... code. + if (*tokens)[tok].Data != "struct" { + errOut("Unexpected use of raw operator in a statement", out.Data) + } + tok++ + fallthrough + case "struct": + // Check for defword, (), and {} then dip + if (*tokens)[tok].Type != DEFWORD { + errOut("Expected defword after struct keyword.", (*tokens)[tok]) + } + tmp.Data = (*tokens)[tok] + out.Sub = append(out.Sub, tmp) + tok++ + if (*tokens)[tok].Data == "(" { + tmp, tok = parseValueList(tokens, tok, max) + out.Sub = append(out.Sub, tmp) + } - switch t.Data { - case ")", "]", "}": - return out, tok - case ",": - tok++ - default: - errOut("Error: unexpected token when parsing a list of types", t) + if (*tokens)[tok].Data != "{" { + errOut("Could not find struct member list", (*tokens)[tok]) } - tmp, tok = parseType(tokens, tok, max, true) - out.Sub = append(out.Sub, tmp) + tmp, tok = parseValueList(tokens, tok, max) + + case "goto", "label": + if (*tokens)[tok].Type != DEFWORD { + errOut("Expected defword after goto or label keyword.", out.Data) + } + tmp.Data = (*tokens)[tok] + tok++ + // Check for a defword and dip + case "continue", "break": + if (*tokens)[tok].Type != LITERAL { + return out, tok + } + tmp.Data = (*tokens)[tok] + tok++ + // Check for a numerical value and dip + case "alloc", "salloc": + // Parse value list + tmp, tok = parseValueList(tokens, tok, max) + case "delete": + // Parse value list + tmp, tok = parseValueList(tokens, tok, max) } + out.Sub = append(out.Sub, tmp) + + return out, tok +} + +func parseDef(tokens *[]Token, tok, max int) (Node, int) { + out := Node{} + out.Data = Token{} + var tmp Node + + + tmp, tok = parseType(tokens, tok, max, false) + out.Sub = append(out.Sub, tmp) + tmp, tok = parseValueList(tokens, tok, max) + out.Sub = append(out.Sub, tmp) + return out, tok } diff --git a/src/tparse/tree-value.go b/src/tparse/tree-value.go index ab73230..af547a5 100644 --- a/src/tparse/tree-value.go +++ b/src/tparse/tree-value.go @@ -314,7 +314,7 @@ func parseTypeParams(tokens *[]Token, tok, max int) (Node, int) { // TODO: make sure this actually works func parseType(tokens *[]Token, tok, max int, param bool) (Node, int) { - out := Node{Data: Token{Type: 10, Data: "type"}} + out := Node{Data: Token{Type: 10, Data: "type"}, IsBlock: false} for ; tok < max; tok++ { t := (*tokens)[tok] @@ -365,6 +365,10 @@ func parseType(tokens *[]Token, tok, max int, param bool) (Node, int) { tmp2, tok = parseValue(tokens, tok + 1, max) tmp.Sub = append(tmp.Sub, tmp2) } + } else if t.Data == ")" || t.Data == "]" || t.Data == "}"{ + // End of type + tok-- + goto TYPEDONE } else { errOut("Error: unexpected delimeter when parsing type", t) } @@ -374,13 +378,14 @@ func parseType(tokens *[]Token, tok, max int, param bool) (Node, int) { } default: - errOut("Error: unexpected token when parsing type", t) + tok-- + goto TYPEDONE } out.Sub = append(out.Sub, tmp) } - - errOut("End of token list when trying to parse type", (*tokens)[max - 1]) + + TYPEDONE: return out, tok } diff --git a/tests/block-test.tnsl b/tests/block-test.tnsl index 6dde05f..c48d7de 100644 --- a/tests/block-test.tnsl +++ b/tests/block-test.tnsl @@ -1,47 +1,49 @@ /# - Copyright 2020 Kyle Gunger + Copyright 2020 Kyle Gunger - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. #/ -/;if (i==0) - ;i = 2 -;/ -/: include - "this" - "that" -:/ +/; main + ;int i = 0 -# ;; can be used as a quick block re-definition + /;if (i==0) + ;i = 2 + ;/ -/;if (i==0) - ;i = 2 -;;else - ;i = 0 -;/ + /: include + "this" + "that" + :/ -# Comment block switching + # ;; can be used as a quick block re-definition -/; if (i == 2) - ;i = 4 -;# - Comment -#; else - ;i = 6 -;/ + /;if (i==0) + ;i = 2 + ;;else + ;i = 0 + ;/ -/; main + # Comment block switching + + /; if (i == 2) + ;i = 4 + ;# + Comment + #; else + ;i = 6 + ;/ ;/ /; module vec @@ -51,17 +53,17 @@ /;method Vector2 /; operator + (~Vector2 v) - ;self.x += `v.x - ;self.y += `v.y + ;self.x += v`.x + ;self.y += v`.y ;/ - /; operator + (int32 a) + /; operator + (int32 a) ;self.x += a ;self.y += a ;/ ;/ - ;struct FVector2 () {} + ;struct FVector2 () {} ;/ \ No newline at end of file diff --git a/tests/literal-test.tnsl b/tests/literal-test.tnsl index 1841159..73f5f77 100644 --- a/tests/literal-test.tnsl +++ b/tests/literal-test.tnsl @@ -15,8 +15,8 @@ #/ # These should all work -;[]char s = "\"" -;[]char st="\\" +;{}char s = "\"" +;{}char st="\\" ;int i = 0 ;int j=1 @@ -40,4 +40,5 @@ ;int k = .1 -;int l = 0x01 \ No newline at end of file +;int l = 0x01 + diff --git a/tests/parameter-test.tnsl b/tests/parameter-test.tnsl index 254db75..96f6d41 100644 --- a/tests/parameter-test.tnsl +++ b/tests/parameter-test.tnsl @@ -13,6 +13,6 @@ See the License for the specific language governing permissions and limitations under the License. #/ - +;int another = 0 /; loop (int initial = 0, complex = 2) [initial < max || complex < 40, initial++, complex += 7, another += 2] ;/ -- cgit v1.2.3