goyacc: provide -p flag to set prefix for names.

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
diff --git a/src/cmd/goyacc/Makefile b/src/cmd/goyacc/Makefile
index 54b8f33..ac0f427 100644
--- a/src/cmd/goyacc/Makefile
+++ b/src/cmd/goyacc/Makefile
@@ -11,7 +11,7 @@
 include ../../Make.cmd
 
 units: goyacc units.y
-	./goyacc units.y
+	./goyacc -p units_ units.y
 	$(GC) y.go
 	$(LD) -o units y.$O
 
diff --git a/src/cmd/goyacc/doc.go b/src/cmd/goyacc/doc.go
index 686f757..aa5bd58 100644
--- a/src/cmd/goyacc/doc.go
+++ b/src/cmd/goyacc/doc.go
@@ -17,7 +17,8 @@
 
 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 @@
 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
diff --git a/src/cmd/goyacc/goyacc.go b/src/cmd/goyacc/goyacc.go
index c9fa6bf..32816b7 100644
--- a/src/cmd/goyacc/goyacc.go
+++ b/src/cmd/goyacc/goyacc.go
@@ -153,9 +153,17 @@
 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 @@
 	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 @@
 		fmt.Fprintf(stderr, "yacc: stack size too small\n")
 		usage()
 	}
+	yaccpar = strings.Replace(yaccpartext, "$$", prefix, -1)
 	openup()
 
 	defin(0, "$end")
@@ -506,20 +511,20 @@
 	}
 
 	// 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 @@
 				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 @@
 
 	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 @@
 	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 @@
 				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 @@
 				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 @@
 	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 @@
 	}
 
 	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 @@
 // 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 others() {
 	var i, j int
 
-	arout("yyR1", levprd, nprod)
+	arout("R1", levprd, nprod)
 	aryfil(temp1, nprod, 0)
 
 	//
@@ -2739,7 +2744,7 @@
 	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 @@
 			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 @@
 			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 @@
 			}
 		}
 	}
-	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 @@
 	// 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 @@
 	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 @@
 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 @@
 			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 */
 }
 `
diff --git a/src/cmd/goyacc/units.y b/src/cmd/goyacc/units.y
index a7d472f..5d3f9ac 100644
--- a/src/cmd/goyacc/units.y
+++ b/src/cmd/goyacc/units.y
@@ -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 @@
 
 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 @@
 			continue
 		}
 		peekrune = ':'
-		yyParse(UnitsLex(0))
+		units_Parse(UnitsLex(0))
 	}
 
 	/*
@@ -340,7 +343,7 @@
 		}
 		peekrune = '?'
 		nerrors = 0
-		yyParse(UnitsLex(0))
+		units_Parse(UnitsLex(0))
 		if nerrors != 0 {
 			continue
 		}