2015-03-11 3 views
1

Я возвращаюсь к изучению pegjs и, очевидно, еще не понял концепцию ядра. Я пытаюсь разобрать «язык запросов», который начинается с предиката, а затем список операндов (который может включать другой предикат). Так простой пример был бы:PEGJS: Генерация AST для первого синтаксиса предиката

OR(
    "string1" 
    "string2" 
) 

Я хотел выше, чтобы быть преобразованы в:

{ 
    predicate: "OR", 
    operands: [ 
     { 
      type: "STRING", 
      value: "string1" 
     }, 
     { 
      type: "STRING", 
      value: "string2" 
     } 
    ] 
} 

Этот запрос:

OR(
    "string1" 
    "string2" 
    AND (
     "string4" 
     "string5" 
    ) 
    "string3" 
) 

бы стать этим АСТ:

{ 
    predicate: "OR", 
    operands: [ 
     { 
      type: "STRING", 
      value: "string1" 
     }, 
     { 
      type: "STRING", 
      value: "string2" 
     }, 
     { 
      predicate: "AND" 
      operands: [ 
       { 
        type: "STRING", 
        value: "string4" 
       }, 
       { 
        type: "STRING", 
        value: "string5" 
       } 
      ] 
     }, 
     { 
      type: "STRING", 
      value: "string3" 
     } 
    ] 
} 

Моя грамматика приближается, но ха это пара вопросов. Вот текущая грамматика PEGJS. Его можно вставить непосредственно в онлайн-парсер pegjs (http://pegjs.majda.cz/online).

start = 
    or_predicate 

or_predicate 
    = ws* "OR" ws* "(" ws* operands:or_predicate ws* ")" ws* 
    { if(Array.isArray(operands)) { 
     return {predicate: "OR", operands: operands} 
    } else { 
     return {predicate: "OR", operands: [operands] } 
    } 
    } 
/and_predicate 

and_predicate 
    = ws* "AND" ws* "(" operands:and_predicate ")" 
    { if(Array.isArray(operands)) { 
     return {predicate: "AND", operands: operands} 
    } else { 
     return {predicate: "AND", operands: [operands] } 
    } 
    } 
/operands 

operands 
    = ws* values:operand+ { return values; } 

operand = 
    string 
    /ws or_predicate:or_predicate { return or_predicate; } 

string = 
    ws* "\"" value:valid_variable_characters "\"" 
    { return { type: "STRING", value: value.join("")}} 

// List of valid characters for string variables 
valid_variable_characters = 
    [a-zA-Z0-9 _]+ 

ws = 
    [ \t\n] 

Вышеупомянутая грамматика обрабатывает два примера, которые я дал, но я заметил две проблемы, и это приводит меня к следующим трем вопросам.

1. Грамматика терпит неудачу на этом, казалось бы, простой вход (ключ является то, что вложенная ИЛИ приходит сразу после того, как родитель или и «строка» в конце):

OR(
    OR (
     "string1" 
    ) 
    "string2" 
) 

Я не уверен, что вызывает это и как его исправить.

2. Грамматик в настоящее время эта тупой линии для operand правил:

operand = 
    string 
    /ws or_predicate:or_predicate { return or_predicate; } 

Примечания ведущего пробельный (WS) на третьей строке перед or_predicate. Без этого пробела я получаю ошибку «Максимальный размер стека вызовов». Я думаю, что это связано с левой рекурсией, но не положительно. В идеале я хотел бы иметь возможность не иметь необходимых «WS» там так запрос без пробелов, как это будет работать:

OR("string1"OR("string2")"string3") 

Прямо сейчас вы должны искусственно добавить дополнительные пробелы любит это:

OR("string1" OR("string2") "string3") 

3.Am Я неправильно подхожу к этой грамматике? Это только второй, который я попытался, и первый был основан на примере арифметики pegjs, поэтому я понимаю, что могу покончить с этим совершенно неправильно, и именно поэтому я сталкиваюсь с этими проблемами.

Благодарим вас за помощь и время!

С наилучшими пожеланиями,

Ed

ответ

3

Я также совершенно новой для PEG, но вы получите повесить его после того, как в основном смотрит на examples, а не чтение документации.

Попробуйте сравнивая свою версию с этим:

start 
    = ws* predicate:predicate ws* { return predicate; } 

predicate 
    = "OR" ws* "(" operands:operand+ ")" { return { predicate: 'OR', operands: operands }; } 
/"AND" ws* "(" operands:operand+ ")" { return { predicate: 'AND', operands: operands }; } 

operand 
    = ws* predicate:predicate ws* { return predicate; } 
/ws* string:string ws* { return string; } 

string 
    = "\"" chars:valid_variable_characters+ "\"" { return { type: "STRING", value: chars.join("")}} 

valid_variable_characters = [a-zA-Z0-9 _] 
ws = [ \t\n] 

Пробелы не является обязательным.

OR("str1"OR("str2""str3"AND("str4""str5"))"str6") 

Дает:

{ 
    "predicate": "OR", 
    "operands": [ 
     { 
     "type": "STRING", 
     "value": "str1" 
     }, 
     { 
     "predicate": "OR", 
     "operands": [ 
      { 
       "type": "STRING", 
       "value": "str2" 
      }, 
      { 
       "type": "STRING", 
       "value": "str3" 
      }, 
      { 
       "predicate": "AND", 
       "operands": [ 
        { 
        "type": "STRING", 
        "value": "str4" 
        }, 
        { 
        "type": "STRING", 
        "value": "str5" 
        } 
       ] 
      } 
     ] 
     }, 
     { 
     "type": "STRING", 
     "value": "str6" 
     } 
    ] 
} 
+0

Вау спасибо очень много. Я смог использовать ваш пример в качестве базы и создать оттуда. Отлично! – Sarus

 Смежные вопросы

  • Нет связанных вопросов^_^