试试这个:
CHARACTERS
letter = 'A'..'Z' + 'a'..'z' .
digit = "0123456789" .
messageChar = '\u0020'..'\u007e' - ' ' - '(' - ')' .
TOKENS
double = ['-'] digit { digit } [ '.' digit { digit } ] .
ident = letter { letter | digit | '_' } .
message = messageChar { messageChar } CONTEXT (")") .
哦,我必须指出这'\u0020'
是 unicode SPACE,您随后将使用“ - ' '
”删除它。哦, CONTEXT (')')
如果您不需要多个字符的前瞻,则可以使用。这在您的情况下不起作用,因为上面的所有标记都可以出现在')'
.
FWIW:CONTEXT
不消耗封闭的序列,您仍然必须在生产中消耗它。
编辑:
好的,这似乎有效。真的,这次我是认真的:)
CHARACTERS
letter = 'A'..'Z' + 'a'..'z' .
digit = "0123456789" .
// messageChar = '\u0020'..'\u007e' - ' ' - '(' - ')' .
TOKENS
double = ['-'] digit { digit } [ '.' digit { digit } ] .
ident = letter { letter | digit | '_' } .
// message = letter { messageChar } CONTEXT (')') .
// MessageText<out string m> = message (. m = t.val; .)
// .
HearExpr<out HeardMessage message> =
(.
TimeSpan time;
Angle direction = Angle.NaN;
string messageText = "";
.)
"(hear"
TimeSpan<out time>
( "self" | AngleInDegrees<out direction> )
// MessageText<out messageText>
{
ANY (. messageText += t.val; .)
}
')'
(.
message = new HeardMessage(time, direction, new Message(messageText));
.)
.
ANY
将读取字符,直到它命中 ')' 或空格。我把它放在一个连接每个值的循环中,但你可能不想这样做。您可能希望将它放在一个循环中,这样当它看到“这里”而是“这里”时它不会返回“过度”。您可以对 messageText 进行简单的长度检查,或进行其他有效性检查,例如将 t.val 添加到 List 并检查计数。真的什么都有。您还可以使用 RegEx 进行测试,以确保它符合您需要检查的任何模式。
编辑(2011 年 4 月 8 日):
使用带有整数和实数的 Coco/R 的示例
COMPILER Calculator
CHARACTERS
digit = "0123456789".
TOKENS
intNumber = ['-'] digit { digit } .
realNumber = ['-'] { digit } "." digit { digit }
[("e" | "E") ["+" | "-"] digit {digit}] .
PRODUCTIONS
Calculator = { Expression "=" } .
Expression = Term { "+" Term | "-" Term }.
Term = Factor { "*" Factor | "/" Factor }.
Factor = intNumber | realNumber .
END Calculator.
编辑(2011 年 4 月 9 日)
Factor<out double value>
(. value = 0.0; .)
=
(
intNumber
(. value = Convert.ToDouble(t.val); .)
|
realNumber
(. value = Convert.ToDouble(t.val); .)
)
| "(" Expression<out value> ")"
.
或者
Factor<out double value>
(. value = 0.0; .)
=
( intNumber | realNumber )
(. value = Convert.ToDouble(t.val); .)
| "(" Expression<out value> ")"
.