Обучение fslex: Lexer не продвигается

В настоящее время я изучаю лексирование и синтаксический анализ (на основе набора инструментов F#), основанный на анализе простых вычислений, и я застрял в том, что мой лексер не продвигается, чтобы использовать всю строку:

let lexeme = LexBuffer<_>.LexemeString
// ...
rule test = parse
  | digit+  { Console.WriteLine("1_" + (lexeme lexbuf)); test lexbuf; }
  | '+'     { Console.WriteLine("2_" + (lexeme lexbuf)); test lexbuf; }
  | '-'     { Console.WriteLine("3_" + (lexeme lexbuf)); test lexbuf; }
  | '*'     { Console.WriteLine("4_" + (lexeme lexbuf)); test lexbuf; }
  | '/'     { Console.WriteLine("5_" + (lexeme lexbuf)); test lexbuf; }
  | '('     { Console.WriteLine("6_" + (lexeme lexbuf)); test lexbuf; }
  | ')'     { Console.WriteLine("7_" + (lexeme lexbuf)); test lexbuf; }
  | eof     { () }

Обратите внимание, например, финал 'test lexbuf' мне необходимо написать, чтобы гарантировать, что вся строка, которую я предоставляю, используется

Поскольку я не делаю этого в своей реальной реализации, я просто читаю, например, первое число, и это все, что я получаю.

rule calculator = parse
  | digit+  { NUMBER (Convert.ToInt32(lexeme lexbuf)) }
  | '+'     { PLUS }
  | '-'     { MINUS }
  | '*'     { TIMES }
  | '/'     { DIV }
  | '('     { LPAREN }
  | ')'     { RPAREN }
  | eof     { EOF }

Я видел много примеров, структурированных совершенно одинаково. Чего мне не хватает

2 ответа

Решение

Проблема заключалась в том, что вы не можете ожидать, что лексер продвинется сам по себе. Для меня думать об этом как о потоке помогает понять, что происходит.

Опережение работает только в сочетании с парсером. Парсер будет постоянно просить лексера вернуть токены.

Я предполагаю, что у вас, скорее всего, есть пробелы и / или символы новой строки при вводе текста, и поэтому вам нужны правила для их обработки (то есть, отбрасывайте их, продвигая lexbuf, а не создавая токен). Что-то вроде:

let whitespace = [' ' '\t' ]
let newline = ('\n' | '\r' '\n')

...

| whitespace { calculator lexbuf }
| newline    { lexbuf.EndPos <- lexbuf.EndPos.NextLine; calculator lexbuf }
Другие вопросы по тегам