Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report entity name to SDT function #85

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 17 additions & 26 deletions internal/frontend/token/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,33 +91,24 @@ func (T *Token) UintValue() (uint64, error) {
return strconv.ParseUint(string(T.Lit), 10, 64)
}

var (
Copy link
Collaborator

@shivansh shivansh Mar 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure but are the variables holding compiled regular expressions required to be global ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

of course it is not required to be global

in the same time it might be compiled once on package init and used everywhere later

sdtPlaceholdersNum = regexp.MustCompile(`\$(\d+)`)
sdtReplacementNum = []byte(`X[$1]`)
sdtPlaceholdersAll = regexp.MustCompile(`\$\*`)
sdtReplacementAll = []byte(`attribsSliceToEmpyInterfaceSlice(X)...`)
)

Copy link
Collaborator

@shivansh shivansh Mar 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a small comment here explaining the functionality of SDTVal() would be helpful in future. Something along the lines of -

// SDTVal converts a handwritten action expression into an equivalent expression
// usable by gocc during runtime.
// For e.g. the expression `<< $0.(int64) + $2.(int64), nil >>` is converted to
// `X[0].(int64) + X[2].(int64), nil`. `X` usually represents a slice of
// attributes in the code generated by gocc.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there was no such explanation in the original code, so I do did not add it :)

are you sure any explanation is required here? this code is completely self-explaining FMPOV

func (T *Token) SDTVal() string {
sdt := string(T.Lit)
rex, err := regexp.Compile("\\$[0-9]+")
if err != nil {
panic(err)
}
idx := rex.FindAllStringIndex(sdt, -1)
res := ""
if len(idx) <= 0 {
res = sdt
} else {
for i, loc := range idx {
if loc[0] > 0 {
if i > 0 {
res += sdt[idx[i-1][1]:loc[0]]
} else {
res += sdt[0:loc[0]]
}
}
res += "X["
res += sdt[loc[0]+1 : loc[1]]
res += "]"
}
if idx[len(idx)-1][1] < len(sdt) {
res += sdt[idx[len(idx)-1][1]:]
}
}
res := string(
sdtPlaceholdersNum.ReplaceAll(
sdtPlaceholdersAll.ReplaceAll(
T.Lit,
sdtReplacementAll,
),
sdtReplacementNum,
),
)

return strings.TrimSpace(res[2 : len(res)-2])
}

Expand Down
18 changes: 14 additions & 4 deletions internal/parser/gen/golang/actiontable.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,23 +115,33 @@ func getActionRowData(prods ast.SyntaxProdList, set *items.ItemSet, tokMap *toke
switch act1 := act.(type) {
case action.Accept:
pad := max + 1 - len("accept(true),")
data.Actions[i] = fmt.Sprintf("accept(true),%*c/* %s */", pad, ' ', sym)
data.Actions[i] = fmt.Sprintf("accept(true),%*c/* %s */", pad, ' ', safeSym(sym))
case action.Error:
pad := max + 1 - len("nil,")
data.Actions[i] = fmt.Sprintf("nil,%*c/* %s */", pad, ' ', sym)
data.Actions[i] = fmt.Sprintf("nil,%*c/* %s */", pad, ' ', safeSym(sym))
case action.Reduce:
pad := max + 1 - (len("reduce(") + nbytes(int(act1)) + len("),"))
data.Actions[i] = fmt.Sprintf("reduce(%d),%*c/* %s, reduce: %s */", int(act1), pad, ' ', sym, prods[int(act1)].Id)
data.Actions[i] = fmt.Sprintf("reduce(%d),%*c/* %s, reduce: %s */", int(act1), pad, ' ', safeSym(sym), prods[int(act1)].Id)
case action.Shift:
pad := max + 1 - (len("shift(") + nbytes(int(act1)) + len("),"))
data.Actions[i] = fmt.Sprintf("shift(%d),%*c/* %s */", int(act1), pad, ' ', sym)
data.Actions[i] = fmt.Sprintf("shift(%d),%*c/* %s */", int(act1), pad, ' ', safeSym(sym))
default:
panic(fmt.Sprintf("Unknown action type: %T", act1))
}
}
return
}

func safeSym(sym string) string {
switch sym {
// avoid `/* */ */` comment causing compilation error
case `*/`:
return "special case: closing multiline comment sequence"
}

return sym
}

const actionTableSrc = `
// Code generated by gocc; DO NOT EDIT.

Expand Down
2 changes: 1 addition & 1 deletion internal/parser/gen/golang/errors.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/parser/gen/golang/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ const parserSrc = `
package parser

import (
"bytes"
"fmt"
"strings"

parseError "{{.ErrorImport}}"
"{{.TokenImport}}"
Expand Down
16 changes: 15 additions & 1 deletion internal/parser/gen/golang/productionstable.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"bytes"
"fmt"
"path"
"regexp"
"text/template"

"github.com/goccmack/gocc/internal/ast"
Expand All @@ -42,6 +43,8 @@ func GenProductionsTable(pkg, outDir, header string, prods ast.SyntaxProdList, s
io.WriteFile(fname, wr.Bytes())
}

var sdtTokenName = regexp.MustCompile(`\$§`)

func getProdsTab(header string, prods ast.SyntaxProdList, symbols *symbols.Symbols,
itemsets *items.ItemSets, tokMap *token.TokenMap) *prodsTabData {

Expand All @@ -61,7 +64,10 @@ func getProdsTab(header string, prods ast.SyntaxProdList, symbols *symbols.Symbo
}
switch {
case len(prod.Body.SDT) > 0:
data.ProdTab[i].ReduceFunc = fmt.Sprintf("return %s", prod.Body.SDT)
data.ProdTab[i].ReduceFunc = fmt.Sprintf(
"return %s",
sdtTokenName.ReplaceAllString(prod.Body.SDT, fmt.Sprintf("%q", prod.Id)),
)
case isEmpty:
// Empty production with no semantic action.
data.ProdTab[i].ReduceFunc = "return nil, nil"
Expand Down Expand Up @@ -122,4 +128,12 @@ var productionsTable = ProdTab{
},
{{- end }}
}

func attribsSliceToEmpyInterfaceSlice(X []Attrib) []interface{} {
res := make([]interface{}, 0, len(X))
for _, attrib := range X {
res = append(res, attrib)
}
return res
}
`
2 changes: 1 addition & 1 deletion internal/token/gen/golang/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func (m TokenMap) Type(tok string) Type {

func (m TokenMap) TokenString(tok *Token) string {
//TODO: refactor to print pos & token string properly
return fmt.Sprintf("%s(%d,%s)", m.Id(tok.Type), tok.Type, tok.Lit)
return fmt.Sprintf("%s(%d,%q)", m.Id(tok.Type), tok.Type, tok.Lit)
}

func (m TokenMap) StringType(typ Type) string {
Expand Down