A field operand is a field name optionally followed by an alternate
rule name. The field name may be an identifier or one of the special
- names ^ or *.
+ names @ or *.
Field = FieldName [ ":" RuleName ] .
- FieldName = identifier | "^" | "*" .
+ FieldName = identifier | "@" | "*" .
If the field name is an identifier, the current value must be a struct,
and there must be a field with that name in the struct. The same lookup
and an error message is returned. (TODO consider changing the semantics
such that if a field is not found, it evaluates to nil).
- The special name '^' denotes the current value. (TODO see if ^ can
- change to @ or be eliminated).
+ The special name '@' denotes the current value.
The meaning of the special name '*' depends on the type of the current
value:
literal [][]byte; // a list of string segments, possibly starting with '%'
field struct {
- fieldName string; // including "^", "*"
+ fieldName string; // including "@", "*"
ruleName string; // "" if no rule name specified
};
case *field:
// determine field value
switch t.fieldName {
- case "^":
+ case "@":
// field value is current value
case "*":
f = parse(t, ``, fmap1);
verify(t, f, `even odd even odd `, 0, 1, 2, 3);
- f = parse(t, `/ =^:blank; float="#"`, fmap1);
+ f = parse(t, `/ =@:blank; float="#"`, fmap1);
verify(t, f, `# # #`, 0.0, 1.0, 2.0);
- f = parse(t, `float=^:nil`, fmap1);
+ f = parse(t, `float=@:nil`, fmap1);
verify(t, f, ``, 0.0, 1.0, 2.0);
// TODO needs more tests
check(t, `default="%v"`, `42foo3.14`, 42, "foo", 3.14);
check(t, `default="%v"; int="%x"`, `abcdef`, 10, 11, 12, 13, 14, 15);
check(t, `default="%v"; int="%x"`, `ab**ef`, 10, 11, "**", 14, 15);
- check(t, `default="%x"; int=^:default`, `abcdef`, 10, 11, 12, 13, 14, 15);
+ check(t, `default="%x"; int=@:default`, `abcdef`, 10, 11, 12, 13, 14, 15);
}
func (p *parser) init(src []byte) {
p.errors.Init(0);
- p.scanner.Init(src, p, 0);
+ p.scanner.Init(src, p, scanner.AllowIllegalChars); // return '@' as token.ILLEGAL w/o error message
p.next(); // initializes pos, tok, lit
p.packs = make(map [string] string);
p.rules = make(map [string] expr);
func (p *parser) parseField() expr {
var fname string;
switch p.tok {
- case token.XOR:
- fname = "^";
+ case token.ILLEGAL:
+ if string(p.lit) != "@" {
+ return nil;
+ }
+ fname = "@";
p.next();
case token.MUL:
fname = "*";
// Tokens and comments
token.Token =
- ^:string;
+ @:string;
ast.Comment =
// TODO this doesn't indent properly after //-style comments because
{Strings / "\n"};
ast.FuncLit =
- Type " " Body ^:clearOptSemi; // no optional ; after a func literal body
+ Type " " Body @:clearOptSemi; // no optional ; after a func literal body
ast.CompositeLit =
Type "{" {Elts / ", "} "}";
*:signature;
ast.FuncType =
- [Position:isValidPos "func"] ^:signature;
+ [Position:isValidPos "func"] @:signature;
ast.InterfaceType =
"interface"
Tok [" " Label];
stmtList =
- {^ / ^:optSemi "\n"};
+ {@ / @:optSemi "\n"};
blockStmt = // like ast.BlockStmt but w/o indentation
"{"
List:stmtList
"\n"
]
- "}" ^:setOptSemi;
+ "}" @:setOptSemi;
blockStmtPtr =
*:blockStmt;
List:stmtList
) "\n"
]
- "}" ^:setOptSemi;
+ "}" @:setOptSemi;
ast.IfStmt =
"if " [Init "; "] [Cond " "] Body [" else " Else];
{Specs / ";\n"}
) "\n"
]
- ")" ^:setOptSemi
+ ")" @:setOptSemi
| {Specs / ";\n"}
);