func (lp *LanguageParser) Parse() (*parser.Node, error) { sdata := string(lp.data) rn := parser.Node{P: lp, Name: lp.l.ScopeName} defer func() { if r := recover(); r != nil { log.Printf("Panic during parse: %v\n", r) log.Printf("%v", rn) } }() iter := maxiter for i := 0; i < len(sdata) && iter > 0; iter-- { pat, ret := lp.l.RootPattern.Cache(sdata, i) nl := strings.IndexAny(sdata[i:], "\n\r") if nl != -1 { nl += i } if ret == nil { break } else if nl > 0 && nl <= ret[0] { i = nl for i < len(sdata) && (sdata[i] == '\n' || sdata[i] == '\r') { i++ } } else { n := pat.CreateNode(sdata, i, lp, ret) rn.Append(n) i = n.Range.B } } rn.UpdateRange() if len(sdata) != 0 { lut := make([]int, len(sdata)+1) j := 0 for i := range sdata { lut[i] = j j++ } lut[len(sdata)] = len(lp.data) lp.patch(lut, &rn) } if iter == 0 { panic("reached maximum number of iterations") } return &rn, nil }
func (p *Pattern) CreateCaptureNodes(data string, pos int, d parser.DataSource, mo MatchObject, parent *parser.Node, capt Captures) { ranges := make([]text.Region, len(mo)/2) parentIndex := make([]int, len(ranges)) parents := make([]*parser.Node, len(parentIndex)) for i := range ranges { ranges[i] = text.Region{A: mo[i*2+0], B: mo[i*2+1]} if i < 2 { parents[i] = parent continue } r := ranges[i] for j := i - 1; j >= 0; j-- { if ranges[j].Covers(r) { parentIndex[i] = j break } } } for _, v := range capt { i := v.Key if i >= len(parents) || ranges[i].A == -1 { continue } child := &parser.Node{Name: v.Name, Range: ranges[i], P: d} parents[i] = child if i == 0 { parent.Append(child) continue } var p *parser.Node for p == nil { i = parentIndex[i] p = parents[i] } p.Append(child) } }
func (c *Compiler) Recurse(node *parser.Node) string { ret := "" var cf parser.CodeFormatter p := primitives[node.Name] if p != "" { return p } switch node.Name { case "Identifier", "Boolean", "Float", "Integer": return node.Data() case "Text": return "\"" + node.Data() + "\"" case "Comparison": a := c.Recurse(node.Children[0]) cmp := c.Recurse(node.Children[1]) b := c.Recurse(node.Children[2]) return a + cmp + b case "While": return "while (" + c.Recurse(node.Children[0]) + ")\n" + c.Recurse(node.Children[1]) case "If": return "if (" + c.Recurse(node.Children[0]) + ")\n" + c.Recurse(node.Children[1]) case "ElseIf": ret += "else " case "Else": ret += "else\n" case "For": variable := c.Recurse(node.Children[0]) array := c.Recurse(node.Children[1]) block := c.Recurse(node.Children[2]) typeName := "TODO" ret := "for (int i = 0; i < " + array + ".size(); i++)\n{\n\t" ret += typeName + " " + variable + " = " + array + "[i];\n" ret += block[2:] return ret case "NewStatement": return "new " + c.Recurse(node.Children[0]) case "ReturnStatement": return "return " + c.Recurse(node.Children[0]) case "ArrayIndexing": return c.Recurse(node.Children[0]) + "[" + c.Recurse(node.Children[1]) + "]" case "ArraySlicing": id := c.Recurse(node.Children[0]) a := "0" b := id + ".size()" if node.Children[1].Name != "colon" { a = c.Recurse(node.Children[1]) } back := node.Children[len(node.Children)-1] if back.Name != "colon" { b = c.Recurse(back) } return id + ".slice(" + a + ", " + b + ")" case "PostInc": return c.Recurse(node.Children[0]) + "++" case "PostDec": return c.Recurse(node.Children[0]) + "--" case "FunctionCall": ret = node.Children[0].Data() args := "" for _, child := range node.Children[1:] { if args != "" { args += ", " } args += c.Recurse(child) } return ret + "(" + args + ")" case "Class": cn := node.Children[0].Data() c.currentClass = cn cf.Add("class " + cn + "\n{\npublic:\n") cf.Inc() for _, child := range node.Children[1:] { ret := c.Recurse(child) if child.Name == "VariableDeclaration" { ret += ";\n" } cf.Add(ret) } cf.Dec() cf.Add("};\n") c.currentClass = "" return cf.String() case "Assignment": return node.Children[0].Data() + " = " + c.Recurse(node.Children[1]) case "PlusEquals": return node.Children[0].Data() + " += " + c.Recurse(node.Children[1]) case "VariableDeclaration": ret := c.ResolveType(node.Children[0]) + " " n1 := node.Children[1] if n1.Name == "Assignment" { ret += c.Recurse(n1) } else { ret += n1.Data() } return ret case "Block": cf.Add("{\n") cf.Inc() for _, child := range node.Children { r := c.Recurse(child) if !strings.HasSuffix(r, "}\n") { r += ";\n" } cf.Add(r) } cf.Dec() cf.Add("}\n") return cf.String() case "Destructor": c.currentFunction = node.Children[0].Data() ret := "~" + c.currentFunction c.currentFunction = "" return ret + "()\n" + c.Recurse(node.Children[1]) case "FunctionDeclaration": c.currentFunction = node.Children[1].Data() ret := c.ResolveType(node.Children[0]) + " " + c.currentFunction + "(" args := "" for _, child := range node.Children[2 : len(node.Children)-1] { if args != "" { args += ", " } args += c.Recurse(child) } ret += args + ")\n" ret += c.Recurse(node.Children[len(node.Children)-1]) c.currentFunction = "" return ret } for _, child := range node.Children { ret += c.Recurse(child) } return ret }
func (c *Compiler) ResolveType(node *parser.Node) string { if node.Name != "Type" { panic(node) } return node.Data() }
func (c *PyCompiler) Recurse(node *parser.Node) string { ret := "" var cf parser.CodeFormatter p := pyprimitives[node.Name] if p != "" { return p } switch node.Name { case "Identifier", "Float", "Integer": return node.Data() case "Boolean": if node.Data() == "true" { return "True" } else { return "False" } case "Text": return "\"" + node.Data() + "\"" case "Comparison": a := c.Recurse(node.Children[0]) cmp := c.Recurse(node.Children[1]) b := c.Recurse(node.Children[2]) return a + cmp + b case "While": return "while " + c.Recurse(node.Children[0]) + ":\n" + c.Recurse(node.Children[1]) case "If": return "if " + c.Recurse(node.Children[0]) + ":\n" + c.Recurse(node.Children[1]) case "ElseIf": return "el" + c.Recurse(node.Children[0]) case "Else": return "else:" + c.Recurse(node.Children[0]) case "For": variable := c.Recurse(node.Children[0]) array := c.Recurse(node.Children[1]) block := c.Recurse(node.Children[2]) return "for " + variable + " in " + array + ":\n" + block case "NewStatement": return c.Recurse(node.Children[0]) + "()" case "ReturnStatement": return "return " + c.Recurse(node.Children[0]) case "ArrayIndexing": return c.Recurse(node.Children[0]) + "[" + c.Recurse(node.Children[1]) + "]" case "ArraySlicing": id := c.Recurse(node.Children[0]) a := "" b := "" if node.Children[1].Name != "colon" { a = c.Recurse(node.Children[1]) } back := node.Children[len(node.Children)-1] if back.Name != "colon" { b = c.Recurse(back) } return id + "[" + a + ":" + b + "]" case "PostInc": return c.Recurse(node.Children[0]) + " += 1" case "PostDec": return c.Recurse(node.Children[0]) + " -= 1" case "FunctionCall": ret = node.Children[0].Data() args := "" for _, child := range node.Children[1:] { if args != "" { args += ", " } args += c.Recurse(child) } return ret + "(" + args + ")" case "Class": cn := node.Children[0].Data() c.currentClass = cn cf.Add("class " + cn + ":\n") cf.Inc() for _, child := range node.Children[1:] { ret := c.Recurse(child) if child.Name == "VariableDeclaration" { ret += "\n" } cf.Add(ret) } cf.Dec() cf.Add("\n") c.currentClass = "" return cf.String() case "Assignment": return node.Children[0].Data() + " = " + c.Recurse(node.Children[1]) case "PlusEquals": return node.Children[0].Data() + " += " + c.Recurse(node.Children[1]) case "VariableDeclaration": ret := "" //c.ResolveType(node.Children[0]) + " " n1 := node.Children[1] if n1.Name == "Assignment" { ret += c.Recurse(n1) } else { ret += n1.Data() } return ret case "Block": cf.Inc() cf.Add("\t") for _, child := range node.Children { r := c.Recurse(child) if !strings.HasSuffix(r, "\n") { r += "\n" } cf.Add(r) } cf.Dec() return cf.String() case "Destructor": c.currentFunction = node.Children[0].Data() ret := "def __del__(self):\n" c.currentFunction = "" return ret + "" + c.Recurse(node.Children[1]) case "FunctionDeclaration": c.currentFunction = node.Children[1].Data() ret := "def " + c.currentFunction + "(" args := "" if c.currentClass != "" { args += "self" } for _, child := range node.Children[2 : len(node.Children)-1] { if args != "" { args += ", " } args += c.Recurse(child) } ret += args + "):\n" ret += c.Recurse(node.Children[len(node.Children)-1]) c.currentFunction = "" return ret } for _, child := range node.Children { ret += c.Recurse(child) } return ret }