2012-02-14 5 views
1

Я пишу парсер JavaScript с Happy, и мне нужно соответствовать регулярному выражению. Я не хочу полностью анализировать регулярное выражение, просто сохраните его как строку.Как сопоставить регулярное выражение в парсе Happy?

Соответствующая часть моего AST выглядит следующим образом:

data PrimaryExpr 
    -- | Literal integer 
    = ExpLitInt  Integer 
    -- | Literal strings 
    | ExpLitStr  String 
    -- | Identifier 
    | ExpId   String 
    -- | Bracketed expression 
    | ExpBrackExp Expression 
    -- | This (current object) 
    | ExpThis 
    -- | Regular Expression 
    | ExpRegex  String 
    -- | Arrays 
    | ExpArray  ArrayLit 
    -- | Objects 
    | ExpObject  [(PropName, Assignment)] 
    deriving Show 

Это отношение Счастливый код:

primaryExpr :: { PrimaryExpr } 
    : LITINT   { ExpLitInt $1 } 
    | LITSTR   { ExpLitStr $1 } 
    | ID    { ExpId $1 } 
    | THIS   { ExpThis } 
    | regex   { ExpRegex $1 } 
    | arrayLit  { ExpArray $1 } 
    | objectLit  { ExpObject $1 } 
    | '(' expression ')' { ExpBrackExp $2 } 

Мой вопрос, как я должен определить мой regex нетерминальный? Правильно ли такая структура?

regex :: { String } 
    : '/' whatHere? '/' { $2 } 

ответ

3

Вы должны определить регулярное выражение как терминал, который распознается лексером (то есть LITREGEX).

primaryExpr :: { PrimaryExpr } 
    : LITINT   { ExpLitInt $1 } 
    | LITSTR   { ExpLitStr $1 } 
    | LITREGEX  { ExpRegex $1 } 
    | ID    { ExpId $1 } 
    | THIS   { ExpThis } 
    | arrayLit  { ExpArray $1 } 
    | objectLit  { ExpObject $1 } 
    | '(' expression ')' { ExpBrackExp $2 } 
+0

Хорошо, хорошая идея. Это приводит к следующему вопросу - как мне получить Alex lexer для соответствия регулярному выражению? (Я мог бы задать это как отдельный вопрос, если вы думаете, что это лучшая идея?) –

+0

Я не эксперт Алекс, но что-то вроде '\/[^ \ /] * \/{\ s -> LITREGEX. в этом . tail $ s} '. Это не позволяет использовать escape/'' s в регулярном выражении. YMMV – pat

+0

Чтобы сделать это правильно, вам нужно иметь дело с обратными косой чертой '/' и с внутренними символьными классами '/'. – pat

3

Чтобы ответить на вопрос в комментарии, вам нужно немного больше места.

Нечто подобное (растянуты и прокомментированы):

/    forward slash 
( \\.  either: an escaped character 
| [^\[/\\]   anything which isn't/or [ or \ 
| \[     a character class containing: 
    [^\]]*    anything which isn't ] any number of times 
    \]     
)*   any number of times 
/   forward slash 

Сгущенное:

/(\\.|[^\[/\\]|\[[^\]]*\])*/ 
+0

Это замечательно, приветливо. Я думаю, что это лучше, чем у меня. Мне пришлось скрывать косые черты и добавлять модификаторы, так что вот конечный продукт: '\/(\\. | [^ \ [\ /] | \ [[^ \]] * \]) * \/[Gim] * {\ s -> Regex s} ' –

+0

Я собирался сказать, что не был уверен, что вам нужно бежать за Happy, но вы, кажется, поняли это :) – porges

+0

Классы символов позволяют первому персонажу быть ] без закрытия класса – pat

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