mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
122 lines
2.8 KiB
Plaintext
122 lines
2.8 KiB
Plaintext
{
|
|
module Parser where
|
|
import Lexer
|
|
import JQ
|
|
import Text.JSON
|
|
import Debug.Trace
|
|
import Data.List
|
|
import Control.Monad.Error
|
|
import Control.Monad.Reader
|
|
|
|
instance Error (Maybe a) where
|
|
noMsg = Nothing
|
|
strMsg = const Nothing
|
|
|
|
instance (Error a, Error b) => Error (a, b) where
|
|
noMsg = (noMsg, noMsg)
|
|
strMsg s = (strMsg s, strMsg s)
|
|
}
|
|
|
|
%name runParser TopLevel
|
|
%tokentype { Token }
|
|
|
|
%monad { Either String }
|
|
%error { \t -> throwError $ "parse error: unexpected " ++ if null t then [] else (show $ t) }
|
|
|
|
%token
|
|
'|' { TRes "|" }
|
|
'.' { TRes "." }
|
|
'[' { TRes "[" }
|
|
']' { TRes "]" }
|
|
'{' { TRes "{" }
|
|
'}' { TRes "}" }
|
|
'(' { TRes "(" }
|
|
')' { TRes ")" }
|
|
'$' { TRes "$" }
|
|
'as' { TRes "as" }
|
|
',' { TRes "," }
|
|
':' { TRes ":" }
|
|
'==' { TRes "==" }
|
|
'=' { TRes "=" }
|
|
'+' { TRes "+" }
|
|
'def' { TRes "def" }
|
|
';' { TRes ";" }
|
|
'else' { TRes "else" }
|
|
'and' { TRes "and" }
|
|
'or' { TRes "or" }
|
|
Ident { TIdent $$ }
|
|
String { TString $$ }
|
|
Int { TInt $$ }
|
|
|
|
|
|
%left 'else'
|
|
%right '|'
|
|
%left '='
|
|
%left ','
|
|
%left 'and' 'or'
|
|
%nonassoc '=='
|
|
%left '+'
|
|
|
|
%%
|
|
|
|
TopLevel
|
|
: Defn TopLevel { withDefn $1 $2 }
|
|
| Exp { $1 }
|
|
|
|
Exp
|
|
: Exp 'else' Exp { $1 `elsep` $3 }
|
|
| Assign '|' Exp { do { v <- snd $1; setvar (fst $1) v $3 } }
|
|
| Exp '|' Exp { $1 >| $3 }
|
|
| Exp ',' Exp { $1 `mplus` $3 }
|
|
| Exp 'and' Exp { liftM2 andj $1 $3 }
|
|
| Exp 'or' Exp { liftM2 orj $1 $3 }
|
|
| Exp '=' Exp { assignp $1 $3 }
|
|
| Exp '==' Exp { liftM2 eqj (subexp $1) (subexp $3) }
|
|
| Exp '+' Exp { liftM2 plusj (subexp $1) (subexp $3) }
|
|
| Term { $1 }
|
|
|
|
Assign
|
|
: Term 'as' '$' Ident { ($4, $1) }
|
|
|
|
Defn
|
|
: 'def' Ident '=' Exp ';' { ($2, [], $4) }
|
|
| 'def' Ident '(' ParamList ')' '=' Exp ';' { ($2, $4, $7) }
|
|
|
|
ParamList
|
|
: { [] }
|
|
| Ident { [$1] }
|
|
| Ident ';' ParamList { $1:$3 }
|
|
|
|
ExpD
|
|
: ExpD '|' ExpD { $1 >| $3 }
|
|
| ExpD '==' ExpD { liftM2 eqj $1 $3 }
|
|
| Term { $1 }
|
|
|
|
|
|
Term
|
|
: '.' { input }
|
|
| Term '.' Ident { $1 >| index $3 }
|
|
| '.' Ident { index $2 }
|
|
| String { constStr $1 }
|
|
| Term '[' Exp ']' { do {t <- $1; i <- subexp $3; lookupj t i} }
|
|
| Term '[' ']' { $1 >| childp }
|
|
| '(' Exp ')' { $2 }
|
|
| '[' Exp ']' { arrayp $2 }
|
|
| '[' ']' { arrayp (callp "empty" []) }
|
|
| Int { constInt $1 }
|
|
| '{' MkDict '}' { dictp $2 }
|
|
| Ident '(' Exp ')' { callp $1 [$3] }
|
|
| Ident { callp $1 [] }
|
|
| '$' Ident { getvar $2 }
|
|
|
|
MkDict
|
|
: { [] }
|
|
| MkDictPair { [$1] }
|
|
| MkDictPair ',' MkDict { $1:$3 }
|
|
|
|
MkDictPair
|
|
: Ident ':' ExpD { (constStr $1, $3) }
|
|
| Ident { (constStr $1, index $1) }
|
|
| String ':' ExpD { (constStr $1, $3) }
|
|
| '(' Exp ')' ':' ExpD{ ($2, $5) }
|