Попробуйте это:
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'
- это пространство Юникода, которое вы впоследствии удаляете с помощью "- ' '
". О, и вы можете использовать CONTEXT (')')
, если вам не нужно более одного персонажа. В вашем случае это не работает, так как все вышеперечисленные токены могут появляться до ')'
.
FWIW: CONTEXT
не использует вложенную последовательность, вы все равно должны использовать ее в своем производстве.
EDIT:
Хорошо, похоже, это работает. На самом деле, я имею в виду это время:)
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
будет читать символ, пока не попадет ')' или пробел. Я поместил его в цикл, объединяющий каждое значение, но вы можете этого не делать. Вы можете хотеть иметь это в цикле, хотя, чтобы он не возвращал «over», когда он видит «здесь», но «здесь».
Вы можете выполнить простую проверку длины для messageText или другие проверки достоверности, такие как добавление t.val в список и проверку количества. Ничего действительно. Вы также можете выполнить тест с RegEx, чтобы убедиться, что он соответствует любому шаблону, с которым вам нужно проверять.
РЕДАКТИРОВАТЬ (8 апреля 2011 г.):
Пример использования 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.
РЕДАКТИРОВАТЬ (9 апреля 2011 г.)
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> ")"
.