Я хочу сделать синтаксический анализатор счастливым для языка let-in-expression. Например, я хочу разобрать следующую строку:noob хочет сделать синтаксический анализатор для небольшого языка
let x = 4 in x*x
В университете мы изучаем атрибут грамматики, и я хочу использовать эти приемы, чтобы непосредственно вычислить значение разобранного вставленный-выражения. Поэтому в счастливом файле я устанавливаю тип данных функции синтаксического анализа в Int, и я создал новый атрибут, называемый env. Этот атрибут является функцией от String to Int, которая связывает имя переменной со значением. Ссылаясь на моем примере:
env "x" = 4
Теперь я ставлю здесь ниже счастливый файл, где есть моя грамматика:
{
module Parser where
import Token
import Lexer
}
%tokentype { Token }
%token
let { TLet }
in { TIn }
int { TInt $$ }
var { TVar $$ }
'=' { TEq }
'+' { TPlus }
'-' { TMinus }
'*' { TMul }
'/' { TDiv }
'(' { TOB }
')' { TCB }
%name parse
%attributetype { Int }
%attribute env { String -> Int }
%error { parseError }
%%
Exp : let var '=' Exp in Exp
{
$4.env = $$.env;
$2.env = (\_ -> 0);
$6.env = (\str -> if str == $2 then $4 else 0);
$$ = $6;
}
| Exp1
{
$1.env = $$.env;
$$ = $1;
}
Exp1 : Exp1 '+' Term
{
$1.env = $$.env;
$2.env = $$.env;
$$ = $1 + $3;
}
| Exp1 '-' Term
{
$1.env = $$.env;
$2.env = $$.env;
$$ = $1 - $3;
}
| Term
{
$1.env = $$.env;
$$ = $1;
}
Term : Term '*' Factor
{
$1.env = $$.env;
$2.env = $$.env;
$$ = $1 * $3;
}
| Term '/' Factor
{
$1.env = $$.env;
$2.env = $$.env;
$$ = div $1 $3;
}
| Factor
{
$1.env = $$.env;
$$ = $1;
}
Factor
: int
{
$$ = $1;
}
| var
{
$$ = $$.env $1;
}
| '(' Exp ')'
{
$1.env = $$.env;
$$ = $1;
}
{
parseError :: [Token] -> a
parseError _ = error "Parse error"
}
Когда я загрузить файл Haskell генерируемый из счастливого файла выше, я получаю следующее сообщение об ошибке:
Ambiguous occurrence `Int'
It could refer to either `Parser.Int', defined at parser.hs:271:6
or `Prelude.Int',
imported from `Prelude' at parser.hs:2:8-13
(and originally defined in `GHC.Types')
Я не знаю, почему я получаю это, потому что я не определяю тип Parser.Int в моем счастливом файле. Я попытался заменить Int с Prelude.Int, но я получаю другие ошибки.
Как я могу решить? Могу ли я иметь и некоторые общие советы, если я делаю что-то не оптимальное?
Вместо этого я бы использовал комбинаторы парсера, например parsec. – augustss
Если вас интересуют грамматики атрибутов, система UUAG, как правило, является лучшим выбором, чем Happy. Он гораздо лучше документирован (хотя документы иногда устаревают) и активно поддерживается (из-за того, что он используется компилятором UHC Haskell). –
Спасибо, но я должен использовать счастливый. – optimusfrenk