forked from MontiCore/json
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJSON.mc4
More file actions
107 lines (85 loc) · 4.14 KB
/
JSON.mc4
File metadata and controls
107 lines (85 loc) · 4.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/* (c) https://github.com/MontiCore/monticore */
package de.monticore.lang;
/* This is a MontiCore stable grammar.
* Adaptations -- if any -- are conservative. */
/**
* This grammar describes the JSON language, but it is
* a slight superset to the official JSON standard.
* It is intended for parsing JSON-compliant artifacts. Further well-formedness
* checks are not included, because we assume to parse correctly produced JSON
* documents only.
*
* Please note that JSON (like XML or ASCII) is just a carrier language.
* The concrete JSON dialect and the question, how to recreate the
* real objects / data structures, etc. behind the JSON tree structure
* is beyond this project, but can be applied to the AST defined here.
*/
grammar JSON extends de.monticore.literals.MCCommonLiterals {
/** An ASTJSONDocument represents an input file in JSON format.
@attribute jSONValue The top level values contained in the JSON document.
*/
JSONDocument = JSONValue;
/** An ASTJSONValue represents an arbitrary property value. */
interface JSONValue;
/** An ASTJSONObject is a JSONValue that may contain further properties.
@attribute props The properties of the JSON document.
*/
JSONObject implements JSONValue = "{" prop:(JSONProperty || ",")* "}";
/** An ASTJSONProperty represents elements in a key-value relationship.
@attribute key The unique identifier of a property.
@attribute value The property value associated with the identifier.
*/
JSONProperty = key:String ":" value:JSONValue;
/** An ASTJSONBoolean represents a boolean property value.
@attribute booleanLiteral The actual value.
*/
JSONBoolean implements JSONValue = BooleanLiteral;
/** An ASTJSONString represents a String property value.
@attribute stringLiteral The actual value.
*/
JSONString implements JSONValue = StringLiteral;
/** An ASTJSONNumber represents a number property value.
@attribute signedNumericLiteral The actual value (as integer or double).
*/
JSONNumber implements JSONValue = SignedNumericLiteral;
/** An ASTJSONArray represents an array of multiple property values.
@attribute JSONValues The values in the array.
*/
JSONArray implements JSONValue = "[" (JSONValue || ",")* "]";
/** An ASTJSONNull represents an empty property value.
@attribute nullLiteral The actual "null" value.
*/
JSONNull implements JSONValue = NullLiteral;
/** ASTSignedBasicDoubleLiteral represents a positive or negative double.
Overrides the inherited production to include exponential representations.
@attribute source String-representation (including '"').
*/
SignedBasicDoubleLiteral implements SignedNumericLiteral<1> =
// to prevent spaces between the optional "-" and the number,
// we need to define this slightly more complex nonterminal
// (a pure token would clash with Java tokens if these are added)
negative:["-"] DecimalDoublePointLiteral {noSpace()}? |
DecimalDoublePointLiteral;
/*========================================================================*/
/*============================= LEXER RULES ==============================*/
/*========================================================================*/
// JSON doubles differ from Java doubles in the exponent.
// We therefore define a new token here that acts as literal
// for JSON
token DecimalDoublePointLiteral = Digits '.' (Digits)? (ExponentPart)? |
Digits ExponentPart;
token ExponentPart = ('e' | 'E') ('+' | '-')? Digits;
/*========================================================================*/
/*=========================== AST DEFINITIONS ============================*/
/*========================================================================*/
// because SignedBasicDoubleLiteral is a parsed literal, we add the
// getSource() and getValue() methods by hand.
astrule SignedBasicDoubleLiteral =
method public String getSource() {
return (isNegative()?"-":"") + getDecimalDoublePointLiteral();
}
method public double getValue() {
return de.monticore.literals.MCLiteralsDecoder.decodeDouble(getSource());
}
;
}