]> Cypherpunks repositories - gostls13.git/commitdiff
goyacc: provide -p flag to set prefix for names.
authorRob Pike <r@golang.org>
Tue, 1 Mar 2011 01:43:16 +0000 (17:43 -0800)
committerRob Pike <r@golang.org>
Tue, 1 Mar 2011 01:43:16 +0000 (17:43 -0800)
This should allow multiple goyacc grammars to be
compiled into the same binary. There's a chance it
Fixes #1562.

R=rsc, r2
CC=golang-dev
https://golang.org/cl/4256044

src/cmd/goyacc/Makefile
src/cmd/goyacc/doc.go
src/cmd/goyacc/goyacc.go
src/cmd/goyacc/units.y

index 54b8f3360f03773838a94595ca1c966bc5baf720..ac0f427cc5c1df340a84bb56d9bab0d27db0f1a0 100644 (file)
@@ -11,7 +11,7 @@ GOFILES=\
 include ../../Make.cmd
 
 units: goyacc units.y
-       ./goyacc units.y
+       ./goyacc -p units_ units.y
        $(GC) y.go
        $(LD) -o units y.$O
 
index 686f75745250dacf23dd80b976b94f54ba12e636..aa5bd589321ee79fbd41fed53bc7970aa14aaf8b 100644 (file)
@@ -17,7 +17,8 @@ Yacc adepts will have no trouble adapting to this form of the tool.
 
 The file units.y in this directory is a yacc grammar for a version of
 the Unix tool units, also written in Go and largely transliterated
-from the Plan 9 C version.
+from the Plan 9 C version. It needs the flag "-p units_" (see
+below).
 
 The generated parser is reentrant. Parse expects to be given an
 argument that conforms to the following interface:
@@ -31,8 +32,14 @@ Lex should return the token identifier, and place other token
 information in lval (which replaces the usual yylval).
 Error is equivalent to yyerror in the original yacc.
 
-Code inside the parser may refer to the variable yylex
+Code inside the parser may refer to the variable yylex,
 which holds the yyLexer passed to Parse.
 
+The "-p prefix" flag to goyacc sets the prefix, by default yy, that
+begins the names of symbols, including types, the parser, and the
+lexer, generated and referenced by goyacc's generated code.  Setting
+it to distinct values allows multiple grammars to be used in a
+single binary.
+
 */
 package documentation
index c9fa6bfb96f158027591e58922a6d6b5c643e633..32816b7009c02486a5d2773d2cfaaea9ca7924ff 100644 (file)
@@ -153,9 +153,17 @@ var ftable *bufio.Writer    // y.go file
 var fcode = &bytes.Buffer{} // saved code
 var foutput *bufio.Writer   // y.output file
 
-var oflag string // -o [y.go]          - y.go file
-var vflag string // -v [y.output]      - y.output file
-var lflag bool   // -l                 - disable line directives
+var oflag string  // -o [y.go]         - y.go file
+var vflag string  // -v [y.output]     - y.output file
+var lflag bool    // -l                        - disable line directives
+var prefix string // name prefix for identifiers, default yy
+
+func init() {
+       flag.StringVar(&oflag, "o", "y.go", "parser output")
+       flag.StringVar(&prefix, "p", "yy", "name prefix to use in generated code")
+       flag.StringVar(&vflag, "v", "y.output", "create parsing tables")
+       flag.BoolVar(&lflag, "l", false, "disable line directives")
+}
 
 var stacksize = 200
 
@@ -349,10 +357,6 @@ func setup() {
        stderr = bufio.NewWriter(os.NewFile(2, "stderr"))
        foutput = nil
 
-       flag.StringVar(&oflag, "o", "", "parser output")
-       flag.StringVar(&vflag, "v", "", "create parsing tables")
-       flag.BoolVar(&lflag, "l", false, "disable line directives")
-
        flag.Parse()
        if flag.NArg() != 1 {
                usage()
@@ -362,6 +366,7 @@ func setup() {
                fmt.Fprintf(stderr, "yacc: stack size too small\n")
                usage()
        }
+       yaccpar = strings.Replace(yaccpartext, "$$", prefix, -1)
        openup()
 
        defin(0, "$end")
@@ -506,20 +511,20 @@ outer:
        }
 
        // put out names of token names
-       fmt.Fprintf(ftable, "var\tyyToknames\t =[]string {\n")
+       fmt.Fprintf(ftable, "var\t%sToknames\t =[]string {\n", prefix)
        for i := TOKSTART; i <= ntokens; i++ {
                fmt.Fprintf(ftable, "\t\"%v\",\n", tokset[i].name)
        }
        fmt.Fprintf(ftable, "}\n")
 
        // put out names of state names
-       fmt.Fprintf(ftable, "var\tyyStatenames\t =[]string {\n")
+       fmt.Fprintf(ftable, "var\t%sStatenames\t =[]string {\n", prefix)
        //      for i:=TOKSTART; i<=ntokens; i++ {
        //              fmt.Fprintf(ftable, "\t\"%v\",\n", tokset[i].name);
        //      }
        fmt.Fprintf(ftable, "}\n")
 
-       fmt.Fprintf(fcode, "switch yynt {\n")
+       fmt.Fprintf(fcode, "switch %snt {\n", prefix)
 
        moreprod()
        prdptr[0] = []int{NTBASE, start, 1, 0}
@@ -648,8 +653,8 @@ outer:
                                error("default action causes potential type clash")
                        }
                        fmt.Fprintf(fcode, "\ncase %v:", nprod)
-                       fmt.Fprintf(fcode, "\n\tYYVAL.%v = YYS[yypt-0].%v;",
-                               typeset[tempty], typeset[tempty])
+                       fmt.Fprintf(fcode, "\n\t%sVAL.%v = %sS[%spt-0].%v;",
+                               prefix, typeset[tempty], prefix, prefix, typeset[tempty])
                }
                moreprod()
                prdptr[nprod] = make([]int, mem)
@@ -666,9 +671,9 @@ outer:
 
        fmt.Fprintf(fcode, "\n\t}")
 
-       fmt.Fprintf(ftable, "const      yyEofCode       = 1\n")
-       fmt.Fprintf(ftable, "const      yyErrCode       = 2\n")
-       fmt.Fprintf(ftable, "const      yyMaxDepth      = %v\n", stacksize)
+       fmt.Fprintf(ftable, "const      %sEofCode       = 1\n", prefix)
+       fmt.Fprintf(ftable, "const      %sErrCode       = 2\n", prefix)
+       fmt.Fprintf(ftable, "const      %sMaxDepth      = %v\n", prefix, stacksize)
 
        //
        // copy any postfix code
@@ -1034,7 +1039,7 @@ func cpyunion() {
        if !lflag {
                fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
        }
-       fmt.Fprintf(ftable, "type\tyySymType\tstruct")
+       fmt.Fprintf(ftable, "type\t%sSymType\tstruct", prefix)
 
        level := 0
 
@@ -1197,7 +1202,7 @@ loop:
                                c = getrune(finput)
                        }
                        if c == '$' {
-                               fmt.Fprintf(fcode, "YYVAL")
+                               fmt.Fprintf(fcode, "%sVAL", prefix)
 
                                // put out the proper tag...
                                if ntypes != 0 {
@@ -1258,7 +1263,7 @@ loop:
                                ungetrune(finput, c)
                                continue loop
                        }
-                       fmt.Fprintf(fcode, "YYS[yypt-%v]", max-j-1)
+                       fmt.Fprintf(fcode, "%sS[%spt-%v]", prefix, prefix, max-j-1)
 
                        // put out the proper tag
                        if ntypes != 0 {
@@ -2067,7 +2072,7 @@ func output() {
        var c, u, v int
 
        fmt.Fprintf(ftable, "\n//line yacctab:1\n")
-       fmt.Fprintf(ftable, "var\tyyExca = []int {\n")
+       fmt.Fprintf(ftable, "var\t%sExca = []int {\n", prefix)
 
        noset := mkset()
 
@@ -2140,10 +2145,10 @@ func output() {
        }
 
        fmt.Fprintf(ftable, "}\n")
-       fmt.Fprintf(ftable, "const\tyyNprod\t= %v\n", nprod)
-       fmt.Fprintf(ftable, "const\tyyPrivate\t= %v\n", PRIVATE)
-       fmt.Fprintf(ftable, "var\tyyTokenNames []string\n")
-       fmt.Fprintf(ftable, "var\tyyStates []string\n")
+       fmt.Fprintf(ftable, "const\t%sNprod\t= %v\n", prefix, nprod)
+       fmt.Fprintf(ftable, "const\t%sPrivate\t= %v\n", prefix, PRIVATE)
+       fmt.Fprintf(ftable, "var\t%sTokenNames []string\n", prefix)
+       fmt.Fprintf(ftable, "var\t%sStates []string\n", prefix)
 }
 
 //
@@ -2718,10 +2723,10 @@ nextn:
 // write out the optimized parser
 //
 func aoutput() {
-       fmt.Fprintf(ftable, "const\tyyLast\t= %v\n", maxa+1)
-       arout("yyAct", amem, maxa+1)
-       arout("yyPact", indgo, nstate)
-       arout("yyPgo", pgo, nnonter+1)
+       fmt.Fprintf(ftable, "const\t%sLast\t= %v\n", prefix, maxa+1)
+       arout("Act", amem, maxa+1)
+       arout("Pact", indgo, nstate)
+       arout("Pgo", pgo, nnonter+1)
 }
 
 //
@@ -2730,7 +2735,7 @@ func aoutput() {
 func others() {
        var i, j int
 
-       arout("yyR1", levprd, nprod)
+       arout("R1", levprd, nprod)
        aryfil(temp1, nprod, 0)
 
        //
@@ -2739,7 +2744,7 @@ func others() {
        for i = 1; i < nprod; i++ {
                temp1[i] = len(prdptr[i]) - 2
        }
-       arout("yyR2", temp1, nprod)
+       arout("R2", temp1, nprod)
 
        aryfil(temp1, nstate, -1000)
        for i = 0; i <= ntokens; i++ {
@@ -2752,8 +2757,8 @@ func others() {
                        temp1[j] = -i
                }
        }
-       arout("yyChk", temp1, nstate)
-       arout("yyDef", defact, nstate)
+       arout("Chk", temp1, nstate)
+       arout("Def", defact, nstate)
 
        // put out token translation tables
        // table 1 has 0-256
@@ -2778,7 +2783,7 @@ func others() {
                        temp1[i] = YYLEXUNK
                }
        }
-       arout("yyTok1", temp1, c+1)
+       arout("Tok1", temp1, c+1)
 
        // table 2 has PRIVATE-PRIVATE+256
        aryfil(temp1, 256, 0)
@@ -2797,10 +2802,10 @@ func others() {
                        }
                }
        }
-       arout("yyTok2", temp1, c+1)
+       arout("Tok2", temp1, c+1)
 
        // table 3 has everything else
-       fmt.Fprintf(ftable, "var\tyyTok3\t= []int {\n")
+       fmt.Fprintf(ftable, "var\t%sTok3\t= []int {\n", prefix)
        c = 0
        for i = 1; i <= ntokens; i++ {
                j = tokset[i].value
@@ -2829,13 +2834,14 @@ func others() {
        // copy yaccpar
        fmt.Fprintf(ftable, "\n//line yaccpar:1\n")
 
-       parts := strings.Split(yaccpar, "yyrun()", 2)
+       parts := strings.Split(yaccpar, prefix+"run()", 2)
        fmt.Fprintf(ftable, "%v", parts[0])
        ftable.Write(fcode.Bytes())
        fmt.Fprintf(ftable, "%v", parts[1])
 }
 
 func arout(s string, v []int, n int) {
+       s = prefix + s
        fmt.Fprintf(ftable, "var\t%v\t= []int {\n", s)
        for i := 0; i < n; i++ {
                if i%10 == 0 {
@@ -3076,86 +3082,84 @@ func exit(status int) {
        os.Exit(status)
 }
 
-var yaccpar = `
+var yaccpar string // will be processed version of yaccpartext: s/$$/prefix/g
+var yaccpartext = `
 /*     parser for yacc output  */
 
-var yyDebug = 0
+var $$Debug = 0
 
-type yyLexer interface {
-       Lex(lval *yySymType) int
+type $$Lexer interface {
+       Lex(lval *$$SymType) int
        Error(s string)
 }
 
-const yyFlag = -1000
+const $$Flag = -1000
 
-func yyTokname(yyc int) string {
-       if yyc > 0 && yyc <= len(yyToknames) {
-               if yyToknames[yyc-1] != "" {
-                       return yyToknames[yyc-1]
+func $$Tokname(c int) string {
+       if c > 0 && c <= len($$Toknames) {
+               if $$Toknames[c-1] != "" {
+                       return $$Toknames[c-1]
                }
        }
-       return fmt.Sprintf("tok-%v", yyc)
+       return fmt.Sprintf("tok-%v", c)
 }
 
-func yyStatname(yys int) string {
-       if yys >= 0 && yys < len(yyStatenames) {
-               if yyStatenames[yys] != "" {
-                       return yyStatenames[yys]
+func $$Statname(s int) string {
+       if s >= 0 && s < len($$Statenames) {
+               if $$Statenames[s] != "" {
+                       return $$Statenames[s]
                }
        }
-       return fmt.Sprintf("state-%v", yys)
+       return fmt.Sprintf("state-%v", s)
 }
 
-func yylex1(yylex yyLexer, lval *yySymType) int {
-       var yychar int
-       var c int
-
-       yychar = yylex.Lex(lval)
-       if yychar <= 0 {
-               c = yyTok1[0]
+func $$lex1(lex $$Lexer, lval *$$SymType) int {
+       c := 0
+       char := lex.Lex(lval)
+       if char <= 0 {
+               c = $$Tok1[0]
                goto out
        }
-       if yychar < len(yyTok1) {
-               c = yyTok1[yychar]
+       if char < len($$Tok1) {
+               c = $$Tok1[char]
                goto out
        }
-       if yychar >= yyPrivate {
-               if yychar < yyPrivate+len(yyTok2) {
-                       c = yyTok2[yychar-yyPrivate]
+       if char >= $$Private {
+               if char < $$Private+len($$Tok2) {
+                       c = $$Tok2[char-$$Private]
                        goto out
                }
        }
-       for i := 0; i < len(yyTok3); i += 2 {
-               c = yyTok3[i+0]
-               if c == yychar {
-                       c = yyTok3[i+1]
+       for i := 0; i < len($$Tok3); i += 2 {
+               c = $$Tok3[i+0]
+               if c == char {
+                       c = $$Tok3[i+1]
                        goto out
                }
        }
-       c = 0
 
 out:
        if c == 0 {
-               c = yyTok2[1] /* unknown char */
+               c = $$Tok2[1] /* unknown char */
        }
-       if yyDebug >= 3 {
-               fmt.Printf("lex %U %s\n", uint(yychar), yyTokname(c))
+       if $$Debug >= 3 {
+               fmt.Printf("lex %U %s\n", uint(char), $$Tokname(c))
        }
        return c
 }
 
-func yyParse(yylex yyLexer) int {
-       var yyn int
-       var yylval yySymType
-       var YYVAL yySymType
-       YYS := make([]yySymType, yyMaxDepth)
+func $$Parse($$lex $$Lexer) int {
+       var $$n int
+       var $$lval $$SymType
+       var $$VAL $$SymType
+       $$S := make([]$$SymType, $$MaxDepth)
 
        Nerrs := 0   /* number of errors */
        Errflag := 0 /* error recovery flag */
-       yystate := 0
-       yychar := -1
-       yyp := -1
-       goto yystack
+       $$state := 0
+       $$char := -1
+       $$p := -1
+       goto $$stack
 
 ret0:
        return 0
@@ -3163,80 +3167,80 @@ ret0:
 ret1:
        return 1
 
-yystack:
+$$stack:
        /* put a state and value onto the stack */
-       if yyDebug >= 4 {
-               fmt.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate))
+       if $$Debug >= 4 {
+               fmt.Printf("char %v in %v\n", $$Tokname($$char), $$Statname($$state))
        }
 
-       yyp++
-       if yyp >= len(YYS) {
-               nyys := make([]yySymType, len(YYS)*2)
-               copy(nyys, YYS)
-               YYS = nyys
+       $$p++
+       if $$p >= len($$S) {
+               nyys := make([]$$SymType, len($$S)*2)
+               copy(nyys, $$S)
+               $$S = nyys
        }
-       YYS[yyp] = YYVAL
-       YYS[yyp].yys = yystate
+       $$S[$$p] = $$VAL
+       $$S[$$p].yys = $$state
 
-yynewstate:
-       yyn = yyPact[yystate]
-       if yyn <= yyFlag {
-               goto yydefault /* simple state */
+$$newstate:
+       $$n = $$Pact[$$state]
+       if $$n <= $$Flag {
+               goto $$default /* simple state */
        }
-       if yychar < 0 {
-               yychar = yylex1(yylex, &yylval)
+       if $$char < 0 {
+               $$char = $$lex1($$lex, &$$lval)
        }
-       yyn += yychar
-       if yyn < 0 || yyn >= yyLast {
-               goto yydefault
+       $$n += $$char
+       if $$n < 0 || $$n >= $$Last {
+               goto $$default
        }
-       yyn = yyAct[yyn]
-       if yyChk[yyn] == yychar { /* valid shift */
-               yychar = -1
-               YYVAL = yylval
-               yystate = yyn
+       $$n = $$Act[$$n]
+       if $$Chk[$$n] == $$char { /* valid shift */
+               $$char = -1
+               $$VAL = $$lval
+               $$state = $$n
                if Errflag > 0 {
                        Errflag--
                }
-               goto yystack
+               goto $$stack
        }
 
-yydefault:
+$$default:
        /* default state action */
-       yyn = yyDef[yystate]
-       if yyn == -2 {
-               if yychar < 0 {
-                       yychar = yylex1(yylex, &yylval)
+       $$n = $$Def[$$state]
+       if $$n == -2 {
+               if $$char < 0 {
+                       $$char = $$lex1($$lex, &$$lval)
                }
 
                /* look through exception table */
-               yyxi := 0
+               xi := 0
                for {
-                       if yyExca[yyxi+0] == -1 && yyExca[yyxi+1] == yystate {
+                       if $$Exca[xi+0] == -1 && $$Exca[xi+1] == $$state {
                                break
                        }
-                       yyxi += 2
+                       xi += 2
                }
-               for yyxi += 2; ; yyxi += 2 {
-                       yyn = yyExca[yyxi+0]
-                       if yyn < 0 || yyn == yychar {
+               for xi += 2; ; xi += 2 {
+                       $$n = $$Exca[xi+0]
+                       if $$n < 0 || $$n == $$char {
                                break
                        }
                }
-               yyn = yyExca[yyxi+1]
-               if yyn < 0 {
+               $$n = $$Exca[xi+1]
+               if $$n < 0 {
                        goto ret0
                }
        }
-       if yyn == 0 {
+       if $$n == 0 {
                /* error ... attempt to resume parsing */
                switch Errflag {
                case 0: /* brand new error */
-                       yylex.Error("syntax error")
+                       $$lex.Error("syntax error")
                        Nerrs++
-                       if yyDebug >= 1 {
-                               fmt.Printf("%s", yyStatname(yystate))
-                               fmt.Printf("saw %s\n", yyTokname(yychar))
+                       if $$Debug >= 1 {
+                               fmt.Printf("%s", $$Statname($$state))
+                               fmt.Printf("saw %s\n", $$Tokname($$char))
                        }
                        fallthrough
 
@@ -3244,64 +3248,64 @@ yydefault:
                        Errflag = 3
 
                        /* find a state where "error" is a legal shift action */
-                       for yyp >= 0 {
-                               yyn = yyPact[YYS[yyp].yys] + yyErrCode
-                               if yyn >= 0 && yyn < yyLast {
-                                       yystate = yyAct[yyn] /* simulate a shift of "error" */
-                                       if yyChk[yystate] == yyErrCode {
-                                               goto yystack
+                       for $$p >= 0 {
+                               $$n = $$Pact[$$S[$$p].yys] + $$ErrCode
+                               if $$n >= 0 && $$n < $$Last {
+                                       $$state = $$Act[$$n] /* simulate a shift of "error" */
+                                       if $$Chk[$$state] == $$ErrCode {
+                                               goto $$stack
                                        }
                                }
 
-                               /* the current yyp has no shift onn "error", pop stack */
-                               if yyDebug >= 2 {
+                               /* the current p has no shift onn "error", pop stack */
+                               if $$Debug >= 2 {
                                        fmt.Printf("error recovery pops state %d, uncovers %d\n",
-                                               YYS[yyp].yys, YYS[yyp-1].yys)
+                                               $$S[$$p].yys, $$S[$$p-1].yys)
                                }
-                               yyp--
+                               $$p--
                        }
                        /* there is no state on the stack with an error shift ... abort */
                        goto ret1
 
                case 3: /* no shift yet; clobber input char */
-                       if yyDebug >= 2 {
-                               fmt.Printf("error recovery discards %s\n", yyTokname(yychar))
+                       if $$Debug >= 2 {
+                               fmt.Printf("error recovery discards %s\n", $$Tokname($$char))
                        }
-                       if yychar == yyEofCode {
+                       if $$char == $$EofCode {
                                goto ret1
                        }
-                       yychar = -1
-                       goto yynewstate /* try again in the same state */
+                       $$char = -1
+                       goto $$newstate /* try again in the same state */
                }
        }
 
-       /* reduction by production yyn */
-       if yyDebug >= 2 {
-               fmt.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
+       /* reduction by production $$n */
+       if $$Debug >= 2 {
+               fmt.Printf("reduce %v in:\n\t%v\n", $$n, $$Statname($$state))
        }
 
-       yynt := yyn
-       yypt := yyp
-       _ = yypt                // guard against "declared and not used"
+       $$nt := $$n
+       $$pt := $$p
+       _ = $$pt                // guard against "declared and not used"
 
-       yyp -= yyR2[yyn]
-       YYVAL = YYS[yyp+1]
+       $$p -= $$R2[$$n]
+       $$VAL = $$S[$$p+1]
 
        /* consult goto table to find next state */
-       yyn = yyR1[yyn]
-       yyg := yyPgo[yyn]
-       yyj := yyg + YYS[yyp].yys + 1
+       $$n = $$R1[$$n]
+       $$g := $$Pgo[$$n]
+       $$j := $$g + $$S[$$p].yys + 1
 
-       if yyj >= yyLast {
-               yystate = yyAct[yyg]
+       if $$j >= $$Last {
+               $$state = $$Act[$$g]
        } else {
-               yystate = yyAct[yyj]
-               if yyChk[yystate] != -yyn {
-                       yystate = yyAct[yyg]
+               $$state = $$Act[$$j]
+               if $$Chk[$$state] != -$$n {
+                       $$state = $$Act[$$g]
                }
        }
        // dummy call; replaced with literal code
-       yyrun()
-       goto yystack /* stack new state and value */
+       $$run()
+       goto $$stack /* stack new state and value */
 }
 `
index a7d472fc6c54c1193bf6c477007d35454c2aece3..5d3f9aca2439150e397689123efcf06883213e81 100644 (file)
@@ -6,6 +6,9 @@
 // Distributed under the terms of the Lucent Public License Version 1.02
 // See http://plan9.bell-labs.com/plan9/license.html
 
+// Generate parser with prefix "units_":
+//     goyacc -p "units_"
+
 %{
 
 // units.y
@@ -215,7 +218,7 @@ expr0:
 
 type UnitsLex int
 
-func (UnitsLex) Lex(yylval *yySymType) int {
+func (UnitsLex) Lex(yylval *units_SymType) int {
        var c, i int
 
        c = peekrune
@@ -319,7 +322,7 @@ func main() {
                        continue
                }
                peekrune = ':'
-               yyParse(UnitsLex(0))
+               units_Parse(UnitsLex(0))
        }
 
        /*
@@ -340,7 +343,7 @@ func main() {
                }
                peekrune = '?'
                nerrors = 0
-               yyParse(UnitsLex(0))
+               units_Parse(UnitsLex(0))
                if nerrors != 0 {
                        continue
                }