2016-05-23 9 views
0

У меня есть эта секция грамматики в счастливом парсере, представленном на официальном сайте Happy, но мне нужно более подробное объяснение значения правил в скобках. Вот определение маркерасинтаксис happy parser value

%token 
     let    { TokenLet } 
     in    { TokenIn } 
     int    { TokenInt $$ } 
     var    { TokenVar $$ } 
     '='    { TokenEq } 
     '+'    { TokenPlus } 
     '-'    { TokenMinus } 
     '*'    { TokenTimes } 
     '/'    { TokenDiv } 
     '('    { TokenOB } 
     ')'    { TokenCB } 

и здесь раздел грамматики

Exp : let var '=' Exp in Exp { Let $2 $4 $6 } 
      | Exp1     { Exp1 $1 } 

Exp1 : Exp1 '+' Term   { Plus $1 $3 } 
     | Exp1 '-' Term   { Minus $1 $3 } 
     | Term     { Term $1 } 

Term : Term '*' Factor   { Times $1 $3 } 
     | Term '/' Factor   { Div $1 $3 } 
     | Factor     { Factor $1 } 

Factor    
     : int      { Int $1 } 
     | var      { Var $1 } 
     | '(' Exp ')'    { Brack $2 } 

То, что я понимаю, что лексический, определенные ниже в файле, должны производить маркеры только типа definined, а затем построить разберите дерево, используя грамматику. Но что именно означает «{Пусть $ 2 $ 4 $ 6}"? Я знаю, что $ 2 относится ко второму аргументу правила и так далее, но если кто-то может дать мне «прочитанную человеком версию» правил, я был бы действительно счастлив. Надеюсь, я поняла.

Заранее спасибо.

ответ

1

В разделе %token левый столбец - это имена токенов, используемые в другом месте в грамматике, а справа - шаблон, который может использоваться в операторе case. Где вы видите $$ Happy заменит свою собственную переменную. Поэтому, если в результате парсер ожидает целое число в какой-то момент, тогда у Happy будет оператор case с шаблоном, включающим TokenInt v1234, где бит v1234 - это имя переменной, созданное Happy.

«Пусть» - это конструктор распознавания грамматики. Если вы посмотрите немного ниже в примере страницы вы увидите

data Exp 
    = Let String Exp Exp 
    | Exp1 Exp1 
    deriving Show 

Так Let конструктор принимает строку и два суб-выражения (типа «Exp»). Если вы посмотрите на грамматику, вы увидите, что в правиле let есть шесть элементов. Первая - это просто постоянная строка «let». Это используется сгенерированным парсером, чтобы понять, что он смотрит на предложение «let», но полученное дерево разбора не нуждается в нем. Таким образом, $1 не отображается. Вместо этого первый аргумент для конструктора Let должен быть именем связанной переменной, которая является вторым элементом в правиле грамматики. Следовательно, это $2. Другими словами, это два подвыражения, которые являются $4 и $6 по той же логике.Оба они могут быть произвольно сложными выражениями: Счастливые цифры, где они начинаются и заканчиваются, и анализируют их, следуя другим правилам того, что составляет выражения.

+0

Привет, спасибо всем за ответ. Например, в действии «Плюс $ 1 $ 3» было недостаточно написать $$ = $ 1 + $ 3? – davideb93

+0

«Плюс» - это конструктор, который вы используете в Haskell, а «+» - это то, что вы находите в синтаксисе анализируемого документа. Ваш «$$ = $ 1 + $ 3» не имеет ничего, чтобы связать «+» в документе с «Плюсом» в дереве разбора. –

1

Эта линия одно правило для создания (синтаксического анализа) производство Exp:

Exp : let var '=' Exp in Exp { Let $2 $4 $6 } 

Это соответствует правилу:

if you see "let"  ($1) 
followed by a variable name ($2) 
followed by "="   ($3) 
followed by an Exp  ($4) 
followed by "in"  ($5) 
followed by another Exp ($6) 

затем возвращает значение Let $2 $4 $6. Параметры $n будут заменены значениями каждого подпроизведения. Таким образом, если это правило совпадает, Let функции (которая, вероятно, некоторый конструктор данных) будет вызываться с:

  • значение var маркеров в качестве первого параметра,
  • первого Exp разобран ($ 4) как второй параметр
  • и второй проанализированный Exp ($ 6) в качестве третьего параметра.

Я считаю, что значение маркера var - это имя переменной.

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

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