mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-05-26 11:18:55 -06:00
Merge pull request #45 from GrammaticalFramework/pgf2json
Add export to PGF JSON format
This commit is contained in:
1
gf.cabal
1
gf.cabal
@@ -194,6 +194,7 @@ Library
|
|||||||
GF.Compile.GrammarToCanonical
|
GF.Compile.GrammarToCanonical
|
||||||
GF.Grammar.CanonicalJSON
|
GF.Grammar.CanonicalJSON
|
||||||
GF.Compile.PGFtoJS
|
GF.Compile.PGFtoJS
|
||||||
|
GF.Compile.PGFtoJSON
|
||||||
GF.Compile.PGFtoProlog
|
GF.Compile.PGFtoProlog
|
||||||
GF.Compile.PGFtoPython
|
GF.Compile.PGFtoPython
|
||||||
GF.Compile.ReadFiles
|
GF.Compile.ReadFiles
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import GF.Compile.PGFtoHaskell
|
|||||||
import GF.Compile.PGFtoJava
|
import GF.Compile.PGFtoJava
|
||||||
import GF.Compile.PGFtoProlog
|
import GF.Compile.PGFtoProlog
|
||||||
import GF.Compile.PGFtoJS
|
import GF.Compile.PGFtoJS
|
||||||
|
import GF.Compile.PGFtoJSON
|
||||||
import GF.Compile.PGFtoPython
|
import GF.Compile.PGFtoPython
|
||||||
import GF.Infra.Option
|
import GF.Infra.Option
|
||||||
--import GF.Speech.CFG
|
--import GF.Speech.CFG
|
||||||
@@ -38,6 +39,7 @@ exportPGF opts fmt pgf =
|
|||||||
FmtCanonicalGF -> [] -- canon "gf" (render80 . abstract2canonical)
|
FmtCanonicalGF -> [] -- canon "gf" (render80 . abstract2canonical)
|
||||||
FmtCanonicalJson-> []
|
FmtCanonicalJson-> []
|
||||||
FmtJavaScript -> multi "js" pgf2js
|
FmtJavaScript -> multi "js" pgf2js
|
||||||
|
FmtJSON -> multi "json" pgf2json
|
||||||
FmtPython -> multi "py" pgf2python
|
FmtPython -> multi "py" pgf2python
|
||||||
FmtHaskell -> multi "hs" (grammar2haskell opts name)
|
FmtHaskell -> multi "hs" (grammar2haskell opts name)
|
||||||
FmtJava -> multi "java" (grammar2java opts name)
|
FmtJava -> multi "java" (grammar2java opts name)
|
||||||
|
|||||||
156
src/compiler/GF/Compile/PGFtoJSON.hs
Normal file
156
src/compiler/GF/Compile/PGFtoJSON.hs
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
module GF.Compile.PGFtoJSON (pgf2json) where
|
||||||
|
|
||||||
|
import PGF (showCId)
|
||||||
|
import qualified PGF.Internal as M
|
||||||
|
import PGF.Internal (
|
||||||
|
Abstr,
|
||||||
|
CId,
|
||||||
|
CncCat(..),
|
||||||
|
CncFun(..),
|
||||||
|
Concr,
|
||||||
|
DotPos,
|
||||||
|
Equation(..),
|
||||||
|
Literal(..),
|
||||||
|
PArg(..),
|
||||||
|
PGF,
|
||||||
|
Production(..),
|
||||||
|
Symbol(..),
|
||||||
|
Type,
|
||||||
|
absname,
|
||||||
|
abstract,
|
||||||
|
cflags,
|
||||||
|
cnccats,
|
||||||
|
cncfuns,
|
||||||
|
concretes,
|
||||||
|
funs,
|
||||||
|
productions,
|
||||||
|
sequences,
|
||||||
|
totalCats
|
||||||
|
)
|
||||||
|
|
||||||
|
import qualified Text.JSON as JSON
|
||||||
|
import Text.JSON (JSValue(..))
|
||||||
|
|
||||||
|
import qualified Data.Array.IArray as Array
|
||||||
|
import Data.Map (Map)
|
||||||
|
import qualified Data.Set as Set
|
||||||
|
import qualified Data.Map as Map
|
||||||
|
import qualified Data.IntMap as IntMap
|
||||||
|
|
||||||
|
pgf2json :: PGF -> String
|
||||||
|
pgf2json pgf =
|
||||||
|
JSON.encode $ JSON.makeObj
|
||||||
|
[ ("abstract", json_abstract)
|
||||||
|
, ("concretes", json_concretes)
|
||||||
|
]
|
||||||
|
where
|
||||||
|
n = showCId $ absname pgf
|
||||||
|
as = abstract pgf
|
||||||
|
cs = Map.assocs (concretes pgf)
|
||||||
|
start = showCId $ M.lookStartCat pgf
|
||||||
|
json_abstract = abstract2json n start as
|
||||||
|
json_concretes = JSON.makeObj $ map concrete2json cs
|
||||||
|
|
||||||
|
abstract2json :: String -> String -> Abstr -> JSValue
|
||||||
|
abstract2json name start ds =
|
||||||
|
JSON.makeObj
|
||||||
|
[ ("name", mkJSStr name)
|
||||||
|
, ("startcat", mkJSStr start)
|
||||||
|
, ("funs", JSON.makeObj $ map absdef2json (Map.assocs (funs ds)))
|
||||||
|
]
|
||||||
|
|
||||||
|
absdef2json :: (CId,(Type,Int,Maybe ([Equation],[[M.Instr]]),Double)) -> (String,JSValue)
|
||||||
|
absdef2json (f,(typ,_,_,_)) = (showCId f,sig)
|
||||||
|
where
|
||||||
|
(args,cat) = M.catSkeleton typ
|
||||||
|
sig = JSON.makeObj
|
||||||
|
[ ("args", JSArray $ map (mkJSStr.showCId) args)
|
||||||
|
, ("cat", mkJSStr $ showCId cat)
|
||||||
|
]
|
||||||
|
|
||||||
|
lit2json :: Literal -> JSValue
|
||||||
|
lit2json (LStr s) = mkJSStr s
|
||||||
|
lit2json (LInt n) = mkJSInt n
|
||||||
|
lit2json (LFlt d) = JSRational True (toRational d)
|
||||||
|
|
||||||
|
concrete2json :: (CId,Concr) -> (String,JSValue)
|
||||||
|
concrete2json (c,cnc) = (showCId c,obj)
|
||||||
|
where
|
||||||
|
obj = JSON.makeObj
|
||||||
|
[ ("flags", JSON.makeObj [ (showCId k, lit2json v) | (k,v) <- Map.toList (cflags cnc) ])
|
||||||
|
, ("productions", JSON.makeObj [ (show cat, JSArray (map frule2json (Set.toList set))) | (cat,set) <- IntMap.toList (productions cnc)])
|
||||||
|
, ("functions", JSArray (map ffun2json (Array.elems (cncfuns cnc))))
|
||||||
|
, ("sequences", JSArray (map seq2json (Array.elems (sequences cnc))))
|
||||||
|
, ("categories", JSON.makeObj $ map cats2json (Map.assocs (cnccats cnc)))
|
||||||
|
, ("totalfids", mkJSInt (totalCats cnc))
|
||||||
|
]
|
||||||
|
|
||||||
|
cats2json :: (CId, CncCat) -> (String,JSValue)
|
||||||
|
cats2json (c,CncCat start end _) = (showCId c, ixs)
|
||||||
|
where
|
||||||
|
ixs = JSON.makeObj
|
||||||
|
[ ("start", mkJSInt start)
|
||||||
|
, ("end", mkJSInt end)
|
||||||
|
]
|
||||||
|
|
||||||
|
frule2json :: Production -> JSValue
|
||||||
|
frule2json (PApply fid args) =
|
||||||
|
JSON.makeObj
|
||||||
|
[ ("type", mkJSStr "Apply")
|
||||||
|
, ("fid", mkJSInt fid)
|
||||||
|
, ("args", JSArray (map farg2json args))
|
||||||
|
]
|
||||||
|
frule2json (PCoerce arg) =
|
||||||
|
JSON.makeObj
|
||||||
|
[ ("type", mkJSStr "Coerce")
|
||||||
|
, ("arg", mkJSInt arg)
|
||||||
|
]
|
||||||
|
|
||||||
|
farg2json :: PArg -> JSValue
|
||||||
|
farg2json (PArg hypos fid) =
|
||||||
|
JSON.makeObj
|
||||||
|
[ ("type", mkJSStr "PArg")
|
||||||
|
, ("hypos", JSArray $ map (mkJSInt . snd) hypos)
|
||||||
|
, ("fid", mkJSInt fid)
|
||||||
|
]
|
||||||
|
|
||||||
|
ffun2json :: CncFun -> JSValue
|
||||||
|
ffun2json (CncFun f lins) =
|
||||||
|
JSON.makeObj
|
||||||
|
[ ("name", mkJSStr $ showCId f)
|
||||||
|
, ("lins", JSArray (map mkJSInt (Array.elems lins)))
|
||||||
|
]
|
||||||
|
|
||||||
|
seq2json :: Array.Array DotPos Symbol -> JSValue
|
||||||
|
seq2json seq = JSArray [sym2json s | s <- Array.elems seq]
|
||||||
|
|
||||||
|
sym2json :: Symbol -> JSValue
|
||||||
|
sym2json (SymCat n l) = new "SymCat" [mkJSInt n, mkJSInt l]
|
||||||
|
sym2json (SymLit n l) = new "SymLit" [mkJSInt n, mkJSInt l]
|
||||||
|
sym2json (SymVar n l) = new "SymVar" [mkJSInt n, mkJSInt l]
|
||||||
|
sym2json (SymKS t) = new "SymKS" [mkJSStr t]
|
||||||
|
sym2json (SymKP ts alts) = new "SymKP" [JSArray (map sym2json ts), JSArray (map alt2json alts)]
|
||||||
|
sym2json SymBIND = new "SymKS" [mkJSStr "&+"]
|
||||||
|
sym2json SymSOFT_BIND = new "SymKS" [mkJSStr "&+"]
|
||||||
|
sym2json SymSOFT_SPACE = new "SymKS" [mkJSStr "&+"]
|
||||||
|
sym2json SymCAPIT = new "SymKS" [mkJSStr "&|"]
|
||||||
|
sym2json SymALL_CAPIT = new "SymKS" [mkJSStr "&|"]
|
||||||
|
sym2json SymNE = new "SymNE" []
|
||||||
|
|
||||||
|
alt2json :: ([Symbol],[String]) -> JSValue
|
||||||
|
alt2json (ps,ts) = new "Alt" [JSArray (map sym2json ps), JSArray (map mkJSStr ts)]
|
||||||
|
|
||||||
|
new :: String -> [JSValue] -> JSValue
|
||||||
|
new f xs =
|
||||||
|
JSON.makeObj
|
||||||
|
[ ("type", mkJSStr f)
|
||||||
|
, ("args", JSArray xs)
|
||||||
|
]
|
||||||
|
|
||||||
|
-- | Make JSON value from string
|
||||||
|
mkJSStr :: String -> JSValue
|
||||||
|
mkJSStr = JSString . JSON.toJSString
|
||||||
|
|
||||||
|
-- | Make JSON value from integer
|
||||||
|
mkJSInt :: Integral a => a -> JSValue
|
||||||
|
mkJSInt = JSRational False . toRational
|
||||||
232
src/compiler/GF/Compile/pgf.schema.json
Normal file
232
src/compiler/GF/Compile/pgf.schema.json
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "http://grammaticalframework.org/pgf.schema.json",
|
||||||
|
"type": "object",
|
||||||
|
"title": "PGF JSON Schema",
|
||||||
|
"required": [
|
||||||
|
"abstract",
|
||||||
|
"concretes"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"abstract": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"startcat",
|
||||||
|
"funs"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"startcat": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"funs": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"args",
|
||||||
|
"cat"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"args": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cat": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"concretes": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"required": [
|
||||||
|
"flags",
|
||||||
|
"productions",
|
||||||
|
"functions",
|
||||||
|
"sequences",
|
||||||
|
"categories",
|
||||||
|
"totalfids"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"flags": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": ["string", "number"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"productions": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/apply"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/coerce"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"functions": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"title": "CncFun",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"lins": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sequences": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/sym"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"categories": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"title": "CncCat",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"start",
|
||||||
|
"end"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"start": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"totalfids": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"definitions": {
|
||||||
|
"apply": {
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"fid",
|
||||||
|
"args"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["Apply"]
|
||||||
|
},
|
||||||
|
"fid": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"args": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/parg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"coerce": {
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"arg"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["Coerce"]
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parg": {
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"hypos",
|
||||||
|
"fid"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["PArg"]
|
||||||
|
},
|
||||||
|
"hypos": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fid": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sym": {
|
||||||
|
"title": "Sym",
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"args"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"SymCat",
|
||||||
|
"SymLit",
|
||||||
|
"SymVar",
|
||||||
|
"SymKS",
|
||||||
|
"SymKP",
|
||||||
|
"SymNE"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"args": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/sym"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -90,6 +90,7 @@ data OutputFormat = FmtPGFPretty
|
|||||||
| FmtCanonicalGF
|
| FmtCanonicalGF
|
||||||
| FmtCanonicalJson
|
| FmtCanonicalJson
|
||||||
| FmtJavaScript
|
| FmtJavaScript
|
||||||
|
| FmtJSON
|
||||||
| FmtPython
|
| FmtPython
|
||||||
| FmtHaskell
|
| FmtHaskell
|
||||||
| FmtJava
|
| FmtJava
|
||||||
@@ -328,7 +329,7 @@ optDescr =
|
|||||||
Option ['f'] ["output-format"] (ReqArg outFmt "FMT")
|
Option ['f'] ["output-format"] (ReqArg outFmt "FMT")
|
||||||
(unlines ["Output format. FMT can be one of:",
|
(unlines ["Output format. FMT can be one of:",
|
||||||
"Canonical GF grammar: canonical_gf, canonical_json, (and haskell with option --haskell=concrete)",
|
"Canonical GF grammar: canonical_gf, canonical_json, (and haskell with option --haskell=concrete)",
|
||||||
"Multiple concrete: pgf (default), js, pgf_pretty, prolog, python, ...", -- gar,
|
"Multiple concrete: pgf (default), json, js, pgf_pretty, prolog, python, ...", -- gar,
|
||||||
"Single concrete only: bnf, ebnf, fa, gsl, jsgf, regexp, slf, srgs_xml, srgs_abnf, vxml, ....", -- cf, lbnf,
|
"Single concrete only: bnf, ebnf, fa, gsl, jsgf, regexp, slf, srgs_xml, srgs_abnf, vxml, ....", -- cf, lbnf,
|
||||||
"Abstract only: haskell, ..."]), -- prolog_abs,
|
"Abstract only: haskell, ..."]), -- prolog_abs,
|
||||||
Option [] ["sisr"] (ReqArg sisrFmt "FMT")
|
Option [] ["sisr"] (ReqArg sisrFmt "FMT")
|
||||||
@@ -474,6 +475,7 @@ outputFormatsExpl =
|
|||||||
(("canonical_gf", FmtCanonicalGF),"Canonical GF source files"),
|
(("canonical_gf", FmtCanonicalGF),"Canonical GF source files"),
|
||||||
(("canonical_json", FmtCanonicalJson),"Canonical JSON source files"),
|
(("canonical_json", FmtCanonicalJson),"Canonical JSON source files"),
|
||||||
(("js", FmtJavaScript),"JavaScript (whole grammar)"),
|
(("js", FmtJavaScript),"JavaScript (whole grammar)"),
|
||||||
|
(("json", FmtJSON),"JSON (whole grammar)"),
|
||||||
(("python", FmtPython),"Python (whole grammar)"),
|
(("python", FmtPython),"Python (whole grammar)"),
|
||||||
(("haskell", FmtHaskell),"Haskell (abstract syntax)"),
|
(("haskell", FmtHaskell),"Haskell (abstract syntax)"),
|
||||||
(("java", FmtJava),"Java (abstract syntax)"),
|
(("java", FmtJava),"Java (abstract syntax)"),
|
||||||
|
|||||||
Reference in New Issue
Block a user