Привет всем.
Пытаюсь сделать простое правило Peg (полный код ниже), просто подставляющее в исходную строку вида "Identificator 987654321" префиксы, подтверждающие правильный парсинг, в виде "id:Identificator in:987654321"
Исходная строка такая "iasodurirsadrhf 983475"
Ожидается на выходе "id:iasodurirsadrhf
in:983475"
Компилирую
ncc code/1.n -o bin/1.exe -r PowerPack/Nemerle.Peg.dll -r PowerPack/Nemerle.Peg.Macros.dll
Запускаю из консоли
C:\Nemerle>bin\1.exe
Some ( id:'iasodurirsadrhf'
id:'983475')
Закончено
--------------------------
Неверное выделено жирным. Почему — понять не могу.
Предполагается, что выражение
start: string = (Identifier / integer)*;
парсит сначала идентификатор (например, начиная со строки "983475"), натыкаясь на правило
Identifier:string = !NotFirstIdentifierSymbol IdentifierSymbol+ s;
и, первым делом, проверяет невыполнение правила
NotFirstIdentifierSymbol = notAny / digit;
т.е. проверяет
!(notAny / digit)
т.е. проверяет, что первый символ '9' принадлежит notAny — нет, цифры не принадлежат notAny
затем проверяет что символ '9' принадлежит digit — да принадлежит
Правило истинно, а для продолжения выполнения правила
Identifier:string = !NotFirstIdentifierSymbol IdentifierSymbol+ s;
необходимо, чтобы NotFirstIdentifierSymbol было ложным. Значит, это не Identifier, но выводится всё равно с префиксом "id:"
Что я делаю не так?
Полный код:
using Nemerle.Collections;
using Nemerle.Peg;
using Nemerle.Text;
using Nemerle.Utility;
using Nemerle;
using System;
using System.Collections.Generic;
using SCG = System.Collections.Generic;
// ncc code/1.n -o bin/1.exe -r PowerPack/Nemerle.Peg.dll -r PowerPack/Nemerle.Peg.Macros.dll
namespace buildParser
{
[PegGrammar(start,
grammar
{
any = ['\u0000'..'\uFFFF'];
s : void = ' '*;
digit = ('0' .. '9');
integer:string = digit+ s;
notAny = ('\\'
/ '|'
/ ','
/ '.'
/ '?'
/ ';'
/ ':'
/ '['
/ ']'
/ '('
/ ')'
/ '{'
/ '}'
/ '+'
/ '-'
/ '*'
/ '/'
/ '='
/ '<'
/ '>'
/ '&'
/ '^'
/ '%'
/ '$'
/ '#'
/ '@'
/ '!'
/ '~'
/ '`'
/ '\''
/ '\"'
/ '_'
/ ' '
/ '\t'
/ '\r'
/ '\n'
);
NotFirstIdentifierSymbol = notAny / digit;
IdentifierSymbol = (&'_' / !notAny) any;
Identifier:string = !NotFirstIdentifierSymbol IdentifierSymbol+ s;
start: string = (Identifier / integer)*;
})]
public class BuildParser
{
Identifier(token: NToken) : string
{
def s = GetText(token);
$" id:'$s'";
}
integer(token: NToken) : string
{
" in:'" + GetText(token) + "'";
}
start(strs: List[string]): string
{
def e = strs.GetEnumerator();
def a(b)
{
match (e.MoveNext())
{
| false => b
| _ => a(b + e.Current)
}
};
a("")
}
}
}
def bp = buildParser.BuildParser();
Console.WriteLine(bp.Parse("iasodurirsadrhf 983475"));
Console.Write("Закончено");
_ = Console.ReadLine();