Семантические действия в Coco/ R без найденного токена
Я новичок в coco/R и пытаюсь создать синтаксический анализатор командной строки, чтобы написать скрипт для нашего продукта.
Мои команды выглядят так <commandid> <specifier> {<params>}
(это только образец, а не кокос /R-синтаксис).
Я пытался создать производственные правила, но я не понимаю, как правильно вводится код.
Вот очень очень простой пример-атг:
COMPILER Test
PRODUCTIONS
Test =
"test" (. Console.WriteLine("This should only be printed if 'test' was parsed!"); .)
.
END Test.
Я думал, что это ожидает test
и если и только если он был найден, он вызывает указанную командную строку. Но это не так. Выход:
x
-- line 1 col 1: "test" expected
This should only be printed if 'test' was parsed!
test
This should only be printed if 'test' was parsed!
Если я изменю АТГ, просто добавив |
оно работает. Но теперь возникают новые проблемы, если я пытаюсь использовать больше токенов.
Что я делаю неправильно? Я хочу, чтобы мой код вызывался только при разборе токена.
Вот АТГ, который, кажется, работает, но вызывает другие проблемы:
COMPILER Test
PRODUCTIONS
Test =
"test" (. Console.WriteLine("This should only be printed if 'test' was parsed!"); .)
|
.
END Test.
Полностью опробованный АТГ:
COMPILER Test
public event Action Exit;
public event Action Cls;
public event Action<string, string> CreateChannel;
CHARACTERS
lowerCaseLetter = 'a' .. 'z'.
upperCaseLetter = 'A' .. 'Z'.
letter = upperCaseLetter + lowerCaseLetter.
underscore = '_'.
digit = "0123456789".
cr = '\r'.
lf = '\n'.
tab = '\t'.
anyButQuote = ANY - '"'.
anyButSpace = ANY - ' '.
TOKENS
string = ("\"" { anyButQuote | "\\\"" } "\"") | (anyButSpace { anyButSpace }).
COMMENTS FROM "/*" TO "*/" NESTED
COMMENTS FROM "//" TO lf
IGNORE cr + lf + tab
PRODUCTIONS
Test =
(
"exit" (. this.Exit?.Invoke(); .)
|
"cls" (. this.Cls?.Invoke(); .)
|
ParseCreate
)
.
ParseCreate =
"create"
(
ParseCreateChannel
|
(. this.SyntaxError?.Invoke("Usage: create channel <params>"); .)
)
.
ParseCreateChannel =
"channel"
(
ParseIdParam<out var channelId>
ParseTypeParam<out var channelValueType>
(.
if (channelId != null && channelValueType != null)
this.CreateChannel?.Invoke(channelId, channelValueType);
.)
|
(. this.SyntaxError?.Invoke("Usage: create channel id:<id> type:<type>"); .)
)
.
ParseIdParam<out string id> = (. id = null; .)
(
"id:" string (. id = t.val; .)
|
(. this.SyntaxError?.Invoke("Parameter 'id:<id>' expected."); .)
)
.
ParseTypeParam<out string type> = (. type = null; .)
(
"type:" string (. type = t.val; .)
|
(. this.SyntaxError?.Invoke("Parameter 'type:<type>' expected."); .)
)
.
END Test.
Но для правильного ввода create channel id:theid type:thetype
Я получаю ошибку line 1 col 16: invalid ParseCreateChannel
и я не мог представить почему:-(