Finish variables
This commit is contained in:
parent
89fff8112f
commit
1f98b9c421
7 changed files with 164 additions and 88 deletions
124
parser/parser.go
124
parser/parser.go
|
@ -10,65 +10,89 @@ import (
|
|||
// THE HYLIA PARSER
|
||||
|
||||
type Element struct {
|
||||
Name string
|
||||
Content string
|
||||
FilePath string
|
||||
Name string
|
||||
Content string
|
||||
FilePath string
|
||||
NestedElements []Element
|
||||
Variables map[string]string
|
||||
}
|
||||
|
||||
func ParseFile(filename string) ([]Element, error) {
|
||||
func ParseFile(filename string) ([]Element, map[string]string, error) {
|
||||
// Hey, does the file we're trying to parse actually exist?
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Parse the file, and ask "Is this a Hylia file?"
|
||||
content := string(data)
|
||||
if !strings.Contains(content, "<hylia>")|| !strings.Contains(content, "</hylia>") {
|
||||
return nil, errors.New("The structure of this file is invalid. Are you sure this is a Hylia (.hy) file?")
|
||||
elements, variables, err := parseElements(string(data), filename)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to parse elements: %w", err)
|
||||
}
|
||||
|
||||
// Extract the actual Hylia content
|
||||
start := strings.Index(content, "<hylia>")
|
||||
end := strings.Index(content, "</hylia>")
|
||||
if start == -1 || end == -1 {
|
||||
return nil, errors.New("Missing <hylia> tags. Are you sure this is a Hylia (.hy) file?")
|
||||
}
|
||||
|
||||
content = content[start+len("<hylia>") : end]
|
||||
|
||||
// Extract the custom elements, which are wrapped in <element> tags and handle imports
|
||||
elements := []Element{}
|
||||
lines := strings.Split(content, "\n")
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if strings.HasPrefix(line, "<element") {
|
||||
// Extract the element name
|
||||
name := extractAttributeValue(line, "name")
|
||||
if name == "" {
|
||||
return nil, errors.New("<element> tag is missing a name. ('name' attribute)")
|
||||
}
|
||||
content, err := extractElementContent(line, content)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
elements = append(elements, Element{Name: name, Content: content, FilePath: filename})
|
||||
} else if strings.HasPrefix(line, "<import") {
|
||||
filePath := extractAttributeValue(line, "file")
|
||||
if filePath == "" {
|
||||
return nil, errors.New("<import> tag is missing a file ('file' attribute)")
|
||||
}
|
||||
// Recursively parse
|
||||
importedElements, err := ParseFile(filePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ERROR: Could not import file %s: %w", filePath, err)
|
||||
}
|
||||
elements = append(elements, importedElements...)
|
||||
}
|
||||
}
|
||||
|
||||
return elements, nil
|
||||
|
||||
return elements, variables, nil
|
||||
|
||||
}
|
||||
|
||||
func parseElements(content, filename string) ([]Element, map[string]string, error) {
|
||||
elements := []Element{}
|
||||
variables := make(map[string]string)
|
||||
|
||||
lines := strings.Split(content, "\n")
|
||||
var currentElement *Element
|
||||
var nestedContent strings.Builder
|
||||
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if strings.HasPrefix(line, "<var ") {
|
||||
name := extractAttributeValue(line, "name")
|
||||
if name == "" {
|
||||
return nil, nil, errors.New("Variable is missing a name ('name' attribute)")
|
||||
}
|
||||
valueStart := strings.Index(line, ">")
|
||||
valueEnd := strings.Index(line, "</var>")
|
||||
if valueStart == -1 || valueEnd == -1 {
|
||||
return nil, nil, errors.New("invalid variable structure")
|
||||
}
|
||||
value := strings.TrimSpace(line[valueStart+1 : valueEnd])
|
||||
variables[name] = value
|
||||
|
||||
} else if strings.HasPrefix(line, "<element") {
|
||||
if currentElement != nil {
|
||||
currentElement.Content = nestedContent.String()
|
||||
parsedNested, nestedVars, _ := parseElements(nestedContent.String(), filename)
|
||||
currentElement.NestedElements = parsedNested
|
||||
mergeVariables(variables, nestedVars)
|
||||
elements = append(elements, *currentElement)
|
||||
nestedContent.Reset()
|
||||
}
|
||||
name := extractAttributeValue(line, "name")
|
||||
if name == "" {
|
||||
return nil, nil, errors.New("Element is missing a name ('name' attribute)")
|
||||
}
|
||||
currentElement = &Element{Name: name, FilePath: filename}
|
||||
} else if strings.HasPrefix(line, "</element>") {
|
||||
if currentElement != nil {
|
||||
currentElement.Content = nestedContent.String()
|
||||
parsedNested, nestedVars, _ := parseElements(nestedContent.String(), filename)
|
||||
currentElement.NestedElements = parsedNested
|
||||
mergeVariables(variables, nestedVars)
|
||||
elements = append(elements, *currentElement)
|
||||
nestedContent.Reset()
|
||||
currentElement = nil
|
||||
}
|
||||
} else {
|
||||
if currentElement != nil {
|
||||
nestedContent.WriteString(line + "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
return elements, variables, nil
|
||||
}
|
||||
|
||||
func mergeVariables(target, source map[string]string) {
|
||||
for key, value := range source {
|
||||
target[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
// Extracts an attribute
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue