CIRCT  18.0.0git
OMUtils.cpp
Go to the documentation of this file.
1 //===- OMUtils.cpp - OM Utility Functions ---------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/ADT/SmallVector.h"
13 #include "llvm/ADT/StringRef.h"
14 
15 using namespace circt;
16 using namespace om;
17 
18 namespace {
19 struct PathParser {
20  enum class TokenKind {
21  Space,
22  Tilde,
23  Bar,
24  Colon,
25  Greater,
26  Slash,
27  LBrace,
28  RBrace,
29  Period,
30  Id,
31  Eof
32  };
33 
34  struct Token {
35  TokenKind kind;
36  StringRef spelling;
37  };
38 
39  Token formToken(TokenKind kind, size_t n) {
40  auto s = spelling.take_front(n);
41  spelling = spelling.drop_front(n);
42  return {kind, s};
43  }
44 
45  bool isIDChar(char c) {
46  return c != ' ' && c != '~' && c != '|' && c != ':' && c != '>' &&
47  c != '/' && c != '[' && c != ']' && c != '.';
48  }
49 
50  Token parseToken() {
51  size_t pos = 0;
52  auto size = spelling.size();
53  if (0 == size)
54  return formToken(TokenKind::Eof, pos);
55  auto current = spelling[pos];
56  switch (current) {
57  case '~':
58  return formToken(TokenKind::Tilde, pos + 1);
59  case '|':
60  return formToken(TokenKind::Bar, pos + 1);
61  case ':':
62  return formToken(TokenKind::Colon, pos + 1);
63  case '>':
64  return formToken(TokenKind::Greater, pos + 1);
65  case '/':
66  return formToken(TokenKind::Slash, pos + 1);
67  case '[':
68  return formToken(TokenKind::LBrace, pos + 1);
69  case ']':
70  return formToken(TokenKind::RBrace, pos + 1);
71  case '.':
72  return formToken(TokenKind::Period, pos + 1);
73  default:
74  break;
75  }
76 
77  // Parsing a token.
78  while (pos != size && isIDChar(spelling[pos]))
79  ++pos;
80  return formToken(TokenKind::Id, pos);
81  }
82 
83  ParseResult parseToken(TokenKind kind, StringRef &result) {
84  auto save = spelling;
85  auto token = parseToken();
86  if (token.kind != kind)
87  return spelling = save, failure();
88  result = token.spelling;
89  return success();
90  }
91 
92  ParseResult parseToken(TokenKind kind) {
93  StringRef ignore;
94  return parseToken(kind, ignore);
95  }
96 
97  /// basepath ::= eof | id '/' id (':' id '/' id)* eof
98  ParseResult parseBasePath(PathAttr &pathAttr) {
99  if (succeeded(parseToken(TokenKind::Eof)))
100  return success();
101  SmallVector<PathElement> path;
102  while (true) {
103  StringRef module;
104  StringRef instance;
105  if (parseToken(TokenKind::Id, module) || parseToken(TokenKind::Slash) ||
106  parseToken(TokenKind::Id, instance))
107  return failure();
108  path.emplace_back(StringAttr::get(context, module),
109  StringAttr::get(context, instance));
110  if (parseToken(TokenKind::Colon))
111  break;
112  }
113  pathAttr = PathAttr::get(context, path);
114  if (parseToken(TokenKind::Eof))
115  return failure();
116  return success();
117  }
118 
119  /// path ::= id ('/' id ':' path | ('>' id ('[' id ']' | '.' id)* )?) eof
120  ParseResult parsePath(PathAttr &pathAttr, StringAttr &moduleAttr,
121  StringAttr &refAttr, StringAttr &fieldAttr) {
122  SmallVector<PathElement> path;
123  StringRef module;
124  while (true) {
125  if (parseToken(TokenKind::Id, module))
126  return failure();
127  if (parseToken(TokenKind::Slash))
128  break;
129  StringRef instance;
130  if (parseToken(TokenKind::Id, instance) || parseToken(TokenKind::Colon))
131  return failure();
132  path.emplace_back(StringAttr::get(context, module),
133  StringAttr::get(context, instance));
134  }
135  pathAttr = PathAttr::get(context, path);
136  moduleAttr = StringAttr::get(context, module);
137  if (succeeded(parseToken(TokenKind::Greater))) {
138  StringRef ref;
139  if (parseToken(TokenKind::Id, ref))
140  return failure();
141  refAttr = StringAttr::get(context, ref);
142 
143  SmallString<64> field;
144  while (true) {
145  if (succeeded(parseToken(TokenKind::LBrace))) {
146  StringRef id;
147  if (parseToken(TokenKind::Id, id) || parseToken(TokenKind::RBrace))
148  return failure();
149  field += '[';
150  field += id;
151  field += ']';
152  } else if (succeeded(parseToken(TokenKind::Period))) {
153  StringRef id;
154  if (parseToken(TokenKind::Id, id))
155  return failure();
156  field += '.';
157  field += id;
158  } else {
159  break;
160  }
161  }
162  fieldAttr = StringAttr::get(context, field);
163  } else {
164  refAttr = StringAttr::get(context, "");
165  fieldAttr = StringAttr::get(context, "");
166  }
167  if (parseToken(TokenKind::Eof))
168  return failure();
169  return success();
170  }
171 
172  MLIRContext *context;
173  StringRef spelling;
174 };
175 } // namespace
176 
177 ParseResult circt::om::parseBasePath(MLIRContext *context, StringRef spelling,
178  PathAttr &path) {
179  return PathParser{context, spelling}.parseBasePath(path);
180 }
181 
182 ParseResult circt::om::parsePath(MLIRContext *context, StringRef spelling,
183  PathAttr &path, StringAttr &module,
184  StringAttr &ref, StringAttr &field) {
185  return PathParser{context, spelling}.parsePath(path, module, ref, field);
186 }
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:53
ParseResult parsePath(MLIRContext *context, StringRef spelling, PathAttr &path, StringAttr &module, StringAttr &ref, StringAttr &field)
Parse a target string in to a path.
Definition: OMUtils.cpp:182
ParseResult parseBasePath(MLIRContext *context, StringRef spelling, PathAttr &path)
Parse a target string of the form "Foo/bar:Bar/baz" in to a base path.
Definition: OMUtils.cpp:177
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
Definition: DebugAnalysis.h:21
Definition: om.py:1