Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief This file contains a Bison parser for YAML data.
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 : /* -- Declarations ---------------------------------------------------------------------------------------------------------------------- */
10 :
11 : %require "3.0" /* Require Bison 3 or later */
12 :
13 : %skeleton "lalr1.cc" /* Generate an LALR(1) parser */
14 :
15 : %expect 0 /* We expect no shift/reduce and no reduce/reduce conflicts */
16 :
17 : %define parser_class_name { Parser } /* Call the generator parser class `Parser` */
18 : %define api.prefix {yambi} /* Use namespace `yambi` for parser code */
19 : %define api.token.constructor /* Store type, value and location data in symbol objects */
20 : %define api.value.type variant /* Allow grammar actions to return different types of return values */
21 : %define parse.assert /* Add runtime assertions to make sure symbols are constructed and destructed properly */
22 : %define parse.error verbose /* Use verbose error messages that report error location and expected symbol */
23 : %define parse.trace /* Add code for debugging facilities */
24 :
25 : %parse-param { Lexer& lexer } /* Store reference to lexer in parser object */
26 : %parse-param { Driver& driver } /* Store reference to driver in parser object */
27 :
28 : %locations /* Generate code for location processings */
29 :
30 : /* ======== */
31 : /* = Code = */
32 : /* ======== */
33 :
34 : %initial-action {
35 : // Set filename used by location class
36 63 : @$.begin.filename = @$.end.filename = &driver.filename;
37 : };
38 :
39 : %code requires {
40 : #include <string>
41 : class Driver;
42 : class Lexer;
43 : }
44 :
45 : %code {
46 : # include "driver.hpp"
47 :
48 : #undef yylex
49 : #define yylex lexer.nextToken
50 : }
51 :
52 : /* ========== */
53 : /* = Tokens = */
54 : /* ========== */
55 :
56 : %token END 0 "end of file"
57 : %token <std::string> STREAM_START "start of document"
58 : %token <std::string> STREAM_END "end of document"
59 : %token <std::string> COMMENT "comment"
60 : %token <std::string> PLAIN_SCALAR "plain scalar"
61 : %token <std::string> SINGLE_QUOTED_SCALAR "single quoted scalar"
62 : %token <std::string> DOUBLE_QUOTED_SCALAR "double quoted scalar"
63 : %token <std::string> MAP_START "start of map"
64 : %token <std::string> MAP_END "end of map"
65 : %token <std::string> KEY "key"
66 : %token <std::string> VALUE "value"
67 : %token <std::string> SEQUENCE_START "start of sequence"
68 : %token <std::string> SEQUENCE_END "end of sequence"
69 : %token <std::string> ELEMENT "element"
70 :
71 : /* ================= */
72 : /* = Non-Terminals = */
73 : /* ================= */
74 :
75 : %type <std::string> scalar /* The parser stores scalar values as a string */
76 : %type <bool> child_comments_empty /* This boolean specifies if the rule matched a child or not */
77 :
78 : %%
79 :
80 : /* -- Grammar --------------------------------------------------------------------------------------------------------------------------- */
81 :
82 : yaml : STREAM_START empty_child STREAM_END ;
83 : empty_child : empty | child ;
84 :
85 4 : empty : comments_empty { driver.enterEmpty(); }
86 :
87 : child : comments_empty node comments_empty;
88 : node : value
89 : | map
90 : | sequence
91 : ;
92 :
93 103 : child_comments_empty : child { $$ = true; }
94 2 : | comments { $$ = false; }
95 3 : | %empty { $$ = false; }
96 : ;
97 :
98 : comments_empty : comments | %empty ;
99 : comments: COMMENT
100 : | comments COMMENT
101 : ;
102 :
103 459 : value : scalar { driver.exitValue($scalar); } ;
104 776 : scalar : PLAIN_SCALAR { $$ = $PLAIN_SCALAR; }
105 8 : | SINGLE_QUOTED_SCALAR { $$ = $SINGLE_QUOTED_SCALAR; }
106 260 : | DOUBLE_QUOTED_SCALAR { $$ = $DOUBLE_QUOTED_SCALAR; }
107 : ;
108 :
109 : map : MAP_START pairs MAP_END ;
110 : pairs : pair
111 : | pairs pair
112 : | pairs error /* Allow errors after key-value pairs */
113 : ;
114 324 : pair : KEY key VALUE child_comments_empty { driver.exitPair($child_comments_empty); };
115 324 : key : scalar { driver.exitKey($scalar); } ;
116 :
117 33 : sequence : { driver.enterSequence(); }
118 : SEQUENCE_START elements SEQUENCE_END
119 33 : { driver.exitSequence(); }
120 : ;
121 : elements : element
122 : | elements element
123 : | elements error /* Allow errors after elements of a sequence */
124 : ;
125 81 : element : { driver.enterElement(); } ELEMENT child { driver.exitElement(); };
126 :
127 : %%
128 :
129 : /* -- Epilogue -------------------------------------------------------------------------------------------------------------------------- */
130 :
131 : /**
132 : * @brief Bison calls this method in case of an error.
133 : *
134 : * @param location This value specifies the location of the erroneous input.
135 : * @param message This value stores the error message emitted by the Bison parser.
136 : */
137 11 : void yambi::Parser::error (const location_type& location,
138 : const std::string& message)
139 : {
140 22 : driver.error (location, message, lexer.getText());
141 167 : }
|