config/lang: more implemented
This commit is contained in:
parent
fcdcf117f0
commit
669bdc61f9
|
@ -0,0 +1,7 @@
|
||||||
|
package ast
|
||||||
|
|
||||||
|
// Call represents a function call.
|
||||||
|
type Call struct {
|
||||||
|
Func string
|
||||||
|
Args []Node
|
||||||
|
}
|
|
@ -1,6 +1,14 @@
|
||||||
package ast
|
package ast
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
// VariableAccess represents a variable access.
|
// VariableAccess represents a variable access.
|
||||||
type VariableAccess struct {
|
type VariableAccess struct {
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *VariableAccess) GoString() string {
|
||||||
|
return fmt.Sprintf("*%#v", *n)
|
||||||
|
}
|
||||||
|
|
|
@ -12,13 +12,16 @@ import (
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
node ast.Node
|
node ast.Node
|
||||||
str string
|
nodeList []ast.Node
|
||||||
|
str string
|
||||||
}
|
}
|
||||||
|
|
||||||
%token <str> STRING IDENTIFIER PROGRAM_BRACKET_LEFT PROGRAM_BRACKET_RIGHT
|
%token <str> STRING IDENTIFIER PROGRAM_BRACKET_LEFT PROGRAM_BRACKET_RIGHT
|
||||||
|
%token <str> PAREN_LEFT PAREN_RIGHT COMMA
|
||||||
|
|
||||||
%type <node> expr interpolation literal
|
%type <node> expr interpolation literal
|
||||||
|
%type <nodeList> args
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
@ -27,6 +30,10 @@ top:
|
||||||
{
|
{
|
||||||
parserResult = $1
|
parserResult = $1
|
||||||
}
|
}
|
||||||
|
| interpolation
|
||||||
|
{
|
||||||
|
parserResult = $1
|
||||||
|
}
|
||||||
| literal interpolation
|
| literal interpolation
|
||||||
{
|
{
|
||||||
parserResult = &ast.Concat{
|
parserResult = &ast.Concat{
|
||||||
|
@ -41,14 +48,31 @@ interpolation:
|
||||||
}
|
}
|
||||||
|
|
||||||
expr:
|
expr:
|
||||||
IDENTIFIER
|
literal
|
||||||
{
|
|
||||||
$$ = &ast.VariableAccess{Name: $1}
|
|
||||||
}
|
|
||||||
| literal
|
|
||||||
{
|
{
|
||||||
$$ = $1
|
$$ = $1
|
||||||
}
|
}
|
||||||
|
| IDENTIFIER
|
||||||
|
{
|
||||||
|
$$ = &ast.VariableAccess{Name: $1}
|
||||||
|
}
|
||||||
|
| IDENTIFIER PAREN_LEFT args PAREN_RIGHT
|
||||||
|
{
|
||||||
|
$$ = &ast.Call{Func: $1, Args: $3}
|
||||||
|
}
|
||||||
|
|
||||||
|
args:
|
||||||
|
{
|
||||||
|
$$ = nil
|
||||||
|
}
|
||||||
|
| args COMMA expr
|
||||||
|
{
|
||||||
|
$$ = append($1, $3)
|
||||||
|
}
|
||||||
|
| expr
|
||||||
|
{
|
||||||
|
$$ = append($$, $1)
|
||||||
|
}
|
||||||
|
|
||||||
literal:
|
literal:
|
||||||
STRING
|
STRING
|
||||||
|
|
|
@ -38,9 +38,21 @@ func (x *parserLex) Lex(yylval *parserSymType) int {
|
||||||
return PROGRAM_BRACKET_LEFT
|
return PROGRAM_BRACKET_LEFT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if x.interpolationDepth == 0 {
|
||||||
|
// We're just a normal string that isn't part of any
|
||||||
|
// interpolation yet.
|
||||||
|
x.backup()
|
||||||
|
return x.lexString(yylval, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore all whitespace
|
||||||
|
if unicode.IsSpace(c) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// If we see a double quote and we're in an interpolation, then
|
// If we see a double quote and we're in an interpolation, then
|
||||||
// we are lexing a string.
|
// we are lexing a string.
|
||||||
if c == '"' && x.interpolationDepth > 0 {
|
if c == '"' {
|
||||||
return x.lexString(yylval, true)
|
return x.lexString(yylval, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,16 +60,15 @@ func (x *parserLex) Lex(yylval *parserSymType) int {
|
||||||
case '}':
|
case '}':
|
||||||
x.interpolationDepth--
|
x.interpolationDepth--
|
||||||
return PROGRAM_BRACKET_RIGHT
|
return PROGRAM_BRACKET_RIGHT
|
||||||
|
case '(':
|
||||||
|
return PAREN_LEFT
|
||||||
|
case ')':
|
||||||
|
return PAREN_RIGHT
|
||||||
|
case ',':
|
||||||
|
return COMMA
|
||||||
default:
|
default:
|
||||||
x.backup()
|
x.backup()
|
||||||
if x.interpolationDepth > 0 {
|
return x.lexId(yylval)
|
||||||
// We're within an interpolation.
|
|
||||||
return x.lexId(yylval)
|
|
||||||
} else {
|
|
||||||
// We're just a normal string that isn't part of any
|
|
||||||
// interpolation yet.
|
|
||||||
return x.lexString(yylval, false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,22 @@ func TestLex(t *testing.T) {
|
||||||
"foo ${\"bar\"}",
|
"foo ${\"bar\"}",
|
||||||
[]int{STRING, PROGRAM_BRACKET_LEFT, STRING, PROGRAM_BRACKET_RIGHT, lexEOF},
|
[]int{STRING, PROGRAM_BRACKET_LEFT, STRING, PROGRAM_BRACKET_RIGHT, lexEOF},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"${bar(baz)}",
|
||||||
|
[]int{PROGRAM_BRACKET_LEFT,
|
||||||
|
IDENTIFIER, PAREN_LEFT, IDENTIFIER, PAREN_RIGHT,
|
||||||
|
PROGRAM_BRACKET_RIGHT, lexEOF},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"${bar(baz, foo)}",
|
||||||
|
[]int{PROGRAM_BRACKET_LEFT,
|
||||||
|
IDENTIFIER, PAREN_LEFT,
|
||||||
|
IDENTIFIER, COMMA, IDENTIFIER,
|
||||||
|
PAREN_RIGHT,
|
||||||
|
PROGRAM_BRACKET_RIGHT, lexEOF},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
|
|
|
@ -54,6 +54,35 @@ func TestParse(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"${foo(bar)}",
|
||||||
|
false,
|
||||||
|
&ast.Call{
|
||||||
|
Func: "foo",
|
||||||
|
Args: []ast.Node{
|
||||||
|
&ast.VariableAccess{
|
||||||
|
Name: "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"${foo(bar, baz)}",
|
||||||
|
false,
|
||||||
|
&ast.Call{
|
||||||
|
Func: "foo",
|
||||||
|
Args: []ast.Node{
|
||||||
|
&ast.VariableAccess{
|
||||||
|
Name: "bar",
|
||||||
|
},
|
||||||
|
&ast.VariableAccess{
|
||||||
|
Name: "baz",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
|
|
|
@ -10,21 +10,28 @@ import (
|
||||||
|
|
||||||
//line lang.y:14
|
//line lang.y:14
|
||||||
type parserSymType struct {
|
type parserSymType struct {
|
||||||
yys int
|
yys int
|
||||||
node ast.Node
|
node ast.Node
|
||||||
str string
|
nodeList []ast.Node
|
||||||
|
str string
|
||||||
}
|
}
|
||||||
|
|
||||||
const STRING = 57346
|
const STRING = 57346
|
||||||
const IDENTIFIER = 57347
|
const IDENTIFIER = 57347
|
||||||
const PROGRAM_BRACKET_LEFT = 57348
|
const PROGRAM_BRACKET_LEFT = 57348
|
||||||
const PROGRAM_BRACKET_RIGHT = 57349
|
const PROGRAM_BRACKET_RIGHT = 57349
|
||||||
|
const PAREN_LEFT = 57350
|
||||||
|
const PAREN_RIGHT = 57351
|
||||||
|
const COMMA = 57352
|
||||||
|
|
||||||
var parserToknames = []string{
|
var parserToknames = []string{
|
||||||
"STRING",
|
"STRING",
|
||||||
"IDENTIFIER",
|
"IDENTIFIER",
|
||||||
"PROGRAM_BRACKET_LEFT",
|
"PROGRAM_BRACKET_LEFT",
|
||||||
"PROGRAM_BRACKET_RIGHT",
|
"PROGRAM_BRACKET_RIGHT",
|
||||||
|
"PAREN_LEFT",
|
||||||
|
"PAREN_RIGHT",
|
||||||
|
"COMMA",
|
||||||
}
|
}
|
||||||
var parserStatenames = []string{}
|
var parserStatenames = []string{}
|
||||||
|
|
||||||
|
@ -32,7 +39,7 @@ const parserEofCode = 1
|
||||||
const parserErrCode = 2
|
const parserErrCode = 2
|
||||||
const parserMaxDepth = 200
|
const parserMaxDepth = 200
|
||||||
|
|
||||||
//line lang.y:59
|
//line lang.y:83
|
||||||
|
|
||||||
//line yacctab:1
|
//line yacctab:1
|
||||||
var parserExca = []int{
|
var parserExca = []int{
|
||||||
|
@ -41,41 +48,47 @@ var parserExca = []int{
|
||||||
-2, 0,
|
-2, 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
const parserNprod = 7
|
const parserNprod = 12
|
||||||
const parserPrivate = 57344
|
const parserPrivate = 57344
|
||||||
|
|
||||||
var parserTokenNames []string
|
var parserTokenNames []string
|
||||||
var parserStates []string
|
var parserStates []string
|
||||||
|
|
||||||
const parserLast = 10
|
const parserLast = 18
|
||||||
|
|
||||||
var parserAct = []int{
|
var parserAct = []int{
|
||||||
|
|
||||||
9, 3, 7, 2, 5, 3, 1, 4, 6, 8,
|
7, 14, 15, 11, 10, 4, 5, 5, 4, 9,
|
||||||
|
3, 1, 13, 6, 8, 2, 16, 12,
|
||||||
}
|
}
|
||||||
var parserPact = []int{
|
var parserPact = []int{
|
||||||
|
|
||||||
1, -1000, -2, -1000, -1000, -3, -7, -1000, -1000, -1000,
|
1, -1000, 0, -1000, -1000, 4, -1000, -3, -1000, -5,
|
||||||
|
-1000, 4, -8, -1000, -1000, 4, -1000,
|
||||||
}
|
}
|
||||||
var parserPgo = []int{
|
var parserPgo = []int{
|
||||||
|
|
||||||
0, 8, 7, 3, 6,
|
0, 0, 10, 14, 17, 11,
|
||||||
}
|
}
|
||||||
var parserR1 = []int{
|
var parserR1 = []int{
|
||||||
|
|
||||||
0, 4, 4, 2, 1, 1, 3,
|
0, 5, 5, 5, 2, 1, 1, 1, 4, 4,
|
||||||
|
4, 3,
|
||||||
}
|
}
|
||||||
var parserR2 = []int{
|
var parserR2 = []int{
|
||||||
|
|
||||||
0, 1, 2, 3, 1, 1, 1,
|
0, 1, 1, 2, 3, 1, 1, 4, 0, 3,
|
||||||
|
1, 1,
|
||||||
}
|
}
|
||||||
var parserChk = []int{
|
var parserChk = []int{
|
||||||
|
|
||||||
-1000, -4, -3, 4, -2, 6, -1, 5, -3, 7,
|
-1000, -5, -3, -2, 4, 6, -2, -1, -3, 5,
|
||||||
|
7, 8, -4, -1, 9, 10, -1,
|
||||||
}
|
}
|
||||||
var parserDef = []int{
|
var parserDef = []int{
|
||||||
|
|
||||||
0, -2, 1, 6, 2, 0, 0, 4, 5, 3,
|
0, -2, 1, 2, 11, 0, 3, 0, 5, 6,
|
||||||
|
4, 8, 0, 10, 7, 0, 9,
|
||||||
}
|
}
|
||||||
var parserTok1 = []int{
|
var parserTok1 = []int{
|
||||||
|
|
||||||
|
@ -83,7 +96,7 @@ var parserTok1 = []int{
|
||||||
}
|
}
|
||||||
var parserTok2 = []int{
|
var parserTok2 = []int{
|
||||||
|
|
||||||
2, 3, 4, 5, 6, 7,
|
2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||||
}
|
}
|
||||||
var parserTok3 = []int{
|
var parserTok3 = []int{
|
||||||
0,
|
0,
|
||||||
|
@ -315,34 +328,59 @@ parserdefault:
|
||||||
switch parsernt {
|
switch parsernt {
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
//line lang.y:27
|
//line lang.y:30
|
||||||
{
|
{
|
||||||
parserResult = parserS[parserpt-0].node
|
parserResult = parserS[parserpt-0].node
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
//line lang.y:31
|
//line lang.y:34
|
||||||
|
{
|
||||||
|
parserResult = parserS[parserpt-0].node
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
//line lang.y:38
|
||||||
{
|
{
|
||||||
parserResult = &ast.Concat{
|
parserResult = &ast.Concat{
|
||||||
Exprs: []ast.Node{parserS[parserpt-1].node, parserS[parserpt-0].node},
|
Exprs: []ast.Node{parserS[parserpt-1].node, parserS[parserpt-0].node},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 3:
|
case 4:
|
||||||
//line lang.y:39
|
//line lang.y:46
|
||||||
{
|
{
|
||||||
parserVAL.node = parserS[parserpt-1].node
|
parserVAL.node = parserS[parserpt-1].node
|
||||||
}
|
}
|
||||||
case 4:
|
|
||||||
//line lang.y:45
|
|
||||||
{
|
|
||||||
parserVAL.node = &ast.VariableAccess{Name: parserS[parserpt-0].str}
|
|
||||||
}
|
|
||||||
case 5:
|
case 5:
|
||||||
//line lang.y:49
|
//line lang.y:52
|
||||||
{
|
{
|
||||||
parserVAL.node = parserS[parserpt-0].node
|
parserVAL.node = parserS[parserpt-0].node
|
||||||
}
|
}
|
||||||
case 6:
|
case 6:
|
||||||
//line lang.y:55
|
//line lang.y:56
|
||||||
|
{
|
||||||
|
parserVAL.node = &ast.VariableAccess{Name: parserS[parserpt-0].str}
|
||||||
|
}
|
||||||
|
case 7:
|
||||||
|
//line lang.y:60
|
||||||
|
{
|
||||||
|
parserVAL.node = &ast.Call{Func: parserS[parserpt-3].str, Args: parserS[parserpt-1].nodeList}
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
//line lang.y:65
|
||||||
|
{
|
||||||
|
parserVAL.nodeList = nil
|
||||||
|
}
|
||||||
|
case 9:
|
||||||
|
//line lang.y:69
|
||||||
|
{
|
||||||
|
parserVAL.nodeList = append(parserS[parserpt-2].nodeList, parserS[parserpt-0].node)
|
||||||
|
}
|
||||||
|
case 10:
|
||||||
|
//line lang.y:73
|
||||||
|
{
|
||||||
|
parserVAL.nodeList = append(parserVAL.nodeList, parserS[parserpt-0].node)
|
||||||
|
}
|
||||||
|
case 11:
|
||||||
|
//line lang.y:79
|
||||||
{
|
{
|
||||||
parserVAL.node = &ast.LiteralNode{Value: parserS[parserpt-0].str, Type: ast.TypeString}
|
parserVAL.node = &ast.LiteralNode{Value: parserS[parserpt-0].str, Type: ast.TypeString}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
state 0
|
state 0
|
||||||
$accept: .top $end
|
$accept: .top $end
|
||||||
|
|
||||||
STRING shift 3
|
STRING shift 4
|
||||||
|
PROGRAM_BRACKET_LEFT shift 5
|
||||||
. error
|
. error
|
||||||
|
|
||||||
|
interpolation goto 3
|
||||||
literal goto 2
|
literal goto 2
|
||||||
top goto 1
|
top goto 1
|
||||||
|
|
||||||
|
@ -20,66 +22,123 @@ state 2
|
||||||
top: literal.interpolation
|
top: literal.interpolation
|
||||||
|
|
||||||
PROGRAM_BRACKET_LEFT shift 5
|
PROGRAM_BRACKET_LEFT shift 5
|
||||||
. reduce 1 (src line 25)
|
. reduce 1 (src line 28)
|
||||||
|
|
||||||
interpolation goto 4
|
interpolation goto 6
|
||||||
|
|
||||||
state 3
|
state 3
|
||||||
literal: STRING. (6)
|
top: interpolation. (2)
|
||||||
|
|
||||||
. reduce 6 (src line 53)
|
. reduce 2 (src line 33)
|
||||||
|
|
||||||
|
|
||||||
state 4
|
state 4
|
||||||
top: literal interpolation. (2)
|
literal: STRING. (11)
|
||||||
|
|
||||||
. reduce 2 (src line 30)
|
. reduce 11 (src line 77)
|
||||||
|
|
||||||
|
|
||||||
state 5
|
state 5
|
||||||
interpolation: PROGRAM_BRACKET_LEFT.expr PROGRAM_BRACKET_RIGHT
|
interpolation: PROGRAM_BRACKET_LEFT.expr PROGRAM_BRACKET_RIGHT
|
||||||
|
|
||||||
STRING shift 3
|
STRING shift 4
|
||||||
IDENTIFIER shift 7
|
IDENTIFIER shift 9
|
||||||
. error
|
. error
|
||||||
|
|
||||||
expr goto 6
|
expr goto 7
|
||||||
literal goto 8
|
literal goto 8
|
||||||
|
|
||||||
state 6
|
state 6
|
||||||
interpolation: PROGRAM_BRACKET_LEFT expr.PROGRAM_BRACKET_RIGHT
|
top: literal interpolation. (3)
|
||||||
|
|
||||||
PROGRAM_BRACKET_RIGHT shift 9
|
. reduce 3 (src line 37)
|
||||||
. error
|
|
||||||
|
|
||||||
|
|
||||||
state 7
|
state 7
|
||||||
expr: IDENTIFIER. (4)
|
interpolation: PROGRAM_BRACKET_LEFT expr.PROGRAM_BRACKET_RIGHT
|
||||||
|
|
||||||
. reduce 4 (src line 43)
|
PROGRAM_BRACKET_RIGHT shift 10
|
||||||
|
. error
|
||||||
|
|
||||||
|
|
||||||
state 8
|
state 8
|
||||||
expr: literal. (5)
|
expr: literal. (5)
|
||||||
|
|
||||||
. reduce 5 (src line 48)
|
. reduce 5 (src line 50)
|
||||||
|
|
||||||
|
|
||||||
state 9
|
state 9
|
||||||
interpolation: PROGRAM_BRACKET_LEFT expr PROGRAM_BRACKET_RIGHT. (3)
|
expr: IDENTIFIER. (6)
|
||||||
|
expr: IDENTIFIER.PAREN_LEFT args PAREN_RIGHT
|
||||||
|
|
||||||
. reduce 3 (src line 37)
|
PAREN_LEFT shift 11
|
||||||
|
. reduce 6 (src line 55)
|
||||||
|
|
||||||
|
|
||||||
7 terminals, 5 nonterminals
|
state 10
|
||||||
7 grammar rules, 10/2000 states
|
interpolation: PROGRAM_BRACKET_LEFT expr PROGRAM_BRACKET_RIGHT. (4)
|
||||||
|
|
||||||
|
. reduce 4 (src line 44)
|
||||||
|
|
||||||
|
|
||||||
|
state 11
|
||||||
|
expr: IDENTIFIER PAREN_LEFT.args PAREN_RIGHT
|
||||||
|
args: . (8)
|
||||||
|
|
||||||
|
STRING shift 4
|
||||||
|
IDENTIFIER shift 9
|
||||||
|
. reduce 8 (src line 64)
|
||||||
|
|
||||||
|
expr goto 13
|
||||||
|
literal goto 8
|
||||||
|
args goto 12
|
||||||
|
|
||||||
|
state 12
|
||||||
|
expr: IDENTIFIER PAREN_LEFT args.PAREN_RIGHT
|
||||||
|
args: args.COMMA expr
|
||||||
|
|
||||||
|
PAREN_RIGHT shift 14
|
||||||
|
COMMA shift 15
|
||||||
|
. error
|
||||||
|
|
||||||
|
|
||||||
|
state 13
|
||||||
|
args: expr. (10)
|
||||||
|
|
||||||
|
. reduce 10 (src line 72)
|
||||||
|
|
||||||
|
|
||||||
|
state 14
|
||||||
|
expr: IDENTIFIER PAREN_LEFT args PAREN_RIGHT. (7)
|
||||||
|
|
||||||
|
. reduce 7 (src line 59)
|
||||||
|
|
||||||
|
|
||||||
|
state 15
|
||||||
|
args: args COMMA.expr
|
||||||
|
|
||||||
|
STRING shift 4
|
||||||
|
IDENTIFIER shift 9
|
||||||
|
. error
|
||||||
|
|
||||||
|
expr goto 16
|
||||||
|
literal goto 8
|
||||||
|
|
||||||
|
state 16
|
||||||
|
args: args COMMA expr. (9)
|
||||||
|
|
||||||
|
. reduce 9 (src line 68)
|
||||||
|
|
||||||
|
|
||||||
|
10 terminals, 6 nonterminals
|
||||||
|
12 grammar rules, 17/2000 states
|
||||||
0 shift/reduce, 0 reduce/reduce conflicts reported
|
0 shift/reduce, 0 reduce/reduce conflicts reported
|
||||||
54 working sets used
|
55 working sets used
|
||||||
memory: parser 5/30000
|
memory: parser 11/30000
|
||||||
1 extra closures
|
6 extra closures
|
||||||
5 shift entries, 1 exceptions
|
13 shift entries, 1 exceptions
|
||||||
5 goto entries
|
9 goto entries
|
||||||
0 entries saved by goto default
|
2 entries saved by goto default
|
||||||
Optimizer space used: output 10/30000
|
Optimizer space used: output 18/30000
|
||||||
10 table entries, 0 zero
|
18 table entries, 0 zero
|
||||||
maximum spread: 7, maximum offset: 7
|
maximum spread: 10, maximum offset: 15
|
||||||
|
|
Loading…
Reference in New Issue