0

atom最初にすべてを数値または引用符で囲まれた文字列として解析しようとするルールがあります。それが失敗した場合は、文字列として扱います。

この非常に特定の文字列である特定のケースを除いて、すべてが正常に解析されます。

DUD 123abc

エラーで解析に失敗しExpected " ", "." or [0-9] but "a" found.ます。

私が期待すること: 正常に解析され、文字列 "123abc" が文字列アトムとして返されるはずです。以下の文法コンテンツで、私の失敗した試みのいくつかがコメントアウトされているのを見ることができます。

ヘルプ/ヒント/ポインター/提案​​は大歓迎です!


オンライン PEG.js バージョンで文法を試すことができます。ノード v0.8.23 と pegjs 0.7.0 を使用しています

正しく解析される数値:

  • `123
  • `0
  • `0.
  • 1.
  • `.23
  • `0.23
  • `1.23
  • `0.000
  • . <--- 数値ではなく、エラーでもない文字列として

123abc文字列として解析したいのですが、可能ですか?


これは私の文法ファイル全体です:

start = lines:line+ { return lines; }

// --------------------- LINE STRUCTURE
line = command:command eol { return command; }

command = action:atom args:(sep atom)*
{
  var i = 0, len = 0;

  for (var i = 0, len = args.length; i < len; i++) {
    // discard parsed separator tokens
    args[i] = args[i][1];
  }

  return [action, args];
}

sep = ' '+
eol = "\r" / "\n" / "\r\n"

atom = num:number { return num; }
     / str:string_quoted { return str; }
     / str:string { return str; }

// --------------------- COMMANDS

// TODO:

// --------------------- STRINGS
string = chars:([^" \r\n]+) { return chars.join(''); }

string_quoted = '"' chars:quoted_chars* '"' { return chars.join(''); }
quoted_chars = '\\"' { return '"'; }
             / char:[^"\r\n] { return char; }

// --------------------- NUMBERS
number = integral:('0' / [1-9][0-9]*) fraction:("." [0-9]*)?
{
  if (fraction && fraction.length) {
    fraction = fraction[0] + fraction[1].join('');
  } else {
    fraction = '';
  }

  integral = integral instanceof Array ?
    integral[0] + integral[1].join('') :
    '0';

  return parseFloat(integral + fraction);
}
        / ("." / "0.") fraction:[0-9]+
{
  return parseFloat("0." + fraction.join(''));
}

/*
float = integral:integer? fraction:fraction { return integral + fraction; }

fraction = '.' digits:[0-9]* { return parseFloat('0.' + digits.join('')); }

integer = digits:('0' / [1-9][0-9]*)
{
  if (digits === '0') return 0;
  return parseInt(digits[0] + digits[1].join(''), 10);
}

*/
4

2 に答える 2

3

これは、ルール!([0-9\.]+[^0-9\.])の前に先読みのようなものを追加することで解決しました。number

atomルールが一致することはわかっているので、効果的にnumberルールが少し早く失敗するようにします。うまくいけば、これは将来、あいまいなケースで誰かを助けることができます.

したがって、数の規則は次のようになります。

number = !([0-9\.]+[^0-9\.]) integral:('0' / [1-9][0-9]*) fraction:("." [0-9]*)?

于 2013-04-18T12:03:26.520 に答える
1

number末尾の文字が(英数字ではなく)数字の区切り記号であることを確認することも、より安価に機能したと思います。

number = integral:('0' / [1-9][0-9]*) fraction:("." [0-9]*)? !([0-9A-Za-z]) 
于 2013-04-19T12:47:13.063 に答える