-
Notifications
You must be signed in to change notification settings - Fork 1
/
grammar.h
147 lines (130 loc) · 4.84 KB
/
grammar.h
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FOOMATIC_SHELL_GRAMMAR_H_
#define FOOMATIC_SHELL_GRAMMAR_H_
#include <memory>
#include <string>
#include <utility>
#include <vector>
// This is a definition of the grammar in EBNF notation (ISO/IEC 14977).
//
// Terminal symbols are quoted by '...' or "...". Parenthesis (...) are used
// for grouping. ?...? is used to mark informal description. Other operators:
// - (minus) : exception operator (A-'xx' means "all products of A but 'xx')
// , (comma) : concatenation
// | (pipe) : or
// Repetitions (including an empty product) are denoted by {...}. Empty product
// may be excluded by using minus without following symbol: {...}-.
//
//
// First, a list of all symbols corresponding to a single byte:
//
// ByteAny = ? any byte ? ;
// ByteCommon = ByteAny - "'" - '"' - "`" - "\" ;
// ByteNative = ? any alphanumeric character (0-9,A-Z,a-z) or . (dot) or
// / (slash) or _ (underscore) or - (minus) or + (plus) or
// @ (at) or % (percent) ? ;
// Tabulator = ? byte 0x09 (horizontal tab) ? ;
// EndOfLine = ? byte 0x0A (newline) ? ;
//
//
// These are the tokens extracted by the scanner (see scanner.h):
//
// LiteralString = "'" , { ByteCommon | '"' | "`" | "\" } , "'" ;
// ExecutedString = "`" , { ByteCommon | "'" | '"' | ("\",ByteAny) } , "`" ;
// InterpretedString = '"' , { ByteCommon | "'" | "\" | ("\",'"') | ("\","`")
// | ("\","\") | ExecutedString } , '"' ;
// NativeString = { ByteNative | ("\",ByteAny) }- ;
// Space = { " " | Tabulator }- ;
//
//
// These are the nodes of the parsing tree built by the parser (see parser.h).
//
// StringAtom = { LiteralString | ExecutedString | InterpretedString
// | NativeString | "=" }- ;
//
// Command = {Variable,"=",StringAtom,Space}, Application, {Space,Parameter} ;
// Variable = NativeString ;
// Application = NativeString ;
// Parameter = StringAtom ;
//
// Pipeline = PipeSegment, OptSpace, {"|",OptSpace,PipeSegment,OptSpace} ;
// PipeSegment = ("(",Script,")") | Command ;
// OptSpace = Space | ; (* means "Space or empty product" *)
//
// Script = OptSpace, {SepP,OptSpace}, Pipeline,
// { {SepP,OptSpace}-, Pipeline }, {SepP,OptSpace} ;
// Script = OptSpace , { SepP , OptSpace } ;
// SepP = ";" | EndOfLine ;
//
//
// All conflicts are solved by choosing the largest possible match.
namespace foomatic_shell {
// This represents a single token extracted by the scanner. All bytes from the
// input that are not a part of LiteralString, ExecutedString, NativeString,
// InterpretedString or Space are represented as token of type kByte.
struct Token {
enum Type {
kLiteralString,
kExecutedString,
kInterpretedString,
kNativeString,
kSpace,
kByte,
kEOF
} type;
// For |type|=k*String, the range below points directly to the string
// content (without ', " or `).
// For |type|=kSpace, the range corresponds to the longest possible
// sequence of spaces and tabulators.
// For |type|=kByte, the range points to exactly one character.
// For |type|=kEOF, the range points to the end iterator.
std::string::const_iterator begin;
std::string::const_iterator end;
std::string value;
};
// Represents StringAtom node.
struct StringAtom {
std::vector<Token> components;
};
struct VariableAssignment {
Token variable;
StringAtom new_value;
};
// Represents Command node.
struct Command {
std::vector<VariableAssignment> variables_with_values;
Token application;
std::vector<StringAtom> parameters;
};
struct Script;
// Represents PipeSegment node. Only one of the fields is set.
struct PipeSegment {
std::unique_ptr<Command> command;
std::unique_ptr<Script> script;
};
// Represents Pipeline node.
struct Pipeline {
std::vector<PipeSegment> segments;
};
// Represents Script node.
struct Script {
std::vector<Pipeline> pipelines;
};
// Helper function. Returns string value of given StringAtom.
std::string Value(const StringAtom& str);
// Helper functions. Return positions in the executed script corresponding to
// the beginning of an element given as a parameter.
std::string::const_iterator Position(const PipeSegment& segment);
std::string::const_iterator Position(const Command& cmd);
std::string::const_iterator Position(const Script& script);
// Helper function. Builds an error message containing full script. |source| is
// a script and |position| is a position in this script where the error
// occurred. |msg| contains an error message. The function returns a complete
// error message.
std::string CreateErrorLog(const std::string& source,
std::string::const_iterator position,
const std::string& msg);
} // namespace foomatic_shell
#endif // FOOMATIC_SHELL_GRAMMAR_H_