帮助解析S表达式

发布于 2024-11-10 04:04:09 字数 287 浏览 0 评论 0原文

我正在尝试制作一个简单的绘图程序,该程序读取 translate (rect 10 10 10 10) 50 50。我想做的是将其拆分,以便 50 50translate 一起使用,而 rect 保留所有 10

这是 PostScript 填充。我听说过哈希表和堆栈,但我不知道如何使用它们。我已经完成了其他所有工作(例如所有形状的计算)。我只是不明白如何解析这些行,以便我可以获得指向正确变量的数字。

I'm trying to make a simple drawing program that reads in translate (rect 10 10 10 10) 50 50. What I'm trying to do is split it so that the 50 50 goes with the translate and the rect keeps all the 10s.

This is a PostScript fill. I've heard of hash tables and stacks, but I'm not sure how to use them. I've done everything else (e.x. all the calculations for the shapes). I just don't understand how to parse the lines so that I can get the numbers pointing to the right variables.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

路还长,别太狂 2024-11-17 04:04:09

您的示例看起来像 Lisp s 表达式,因此请尝试搜索“s 表达式解析器”。出现了一些点击。

如果您想“彻底”,您可以将形状例程实现为 C++ 类,使用 SWIG 将它们公开给 GNU Guile,并在 Scheme 中编写您的应用程序。不过,这可能不是您的想法。 :-)

Your example looks like a Lisp s-expression, so try searching for "s-expression parser". A few hits come up.

If you want to go "whole hog", you could implement your shape routines as C++ classes, use SWIG to expose them to GNU Guile, and write your application in Scheme. That is probably not what you had in mind, though. :-)

不知在何时 2024-11-17 04:04:09

嗯,这可能有点过时,但它很简单,而且没有比这更快的了。

void scanWhite(char*& p){
  while(*p==' ') p++;
}

bool seeInt(char*& p, int& num){
  scanWhite(p);
  char* p1 = p;
  bool bNegative = false;
  if (*p=='-'){bNegative = true; p++;)
  if (!isdigit(*p){p = p1; return false;}
  num = 0;
  while(isdigit(*p)){
    num *= 10;
    num += (*p - '0');
    p++;
  }
  if (bNegative) num = - num;
  return true;
}

bool seeWord(char*& p, char* word){
  scanWhite(p);
  int len = strlen(word);
  if (strncmp(p, word, len)==0 && !isalphanumeric(p[len])){
    p += len;
    return true;
  }
  else return false;
}

bool seeChar(char*& p, char c){
  scanWhite(p);
  if (*p != c) return false;
  p++;
  return true;
}

bool parseTranslateRect(char*& p
  , int& x0, int& y0, int& x1, int& y1
  , int& dx, int& dy
  )
{
  if (!seeChar(p, '(')) return false;
  if (!seeWord(p, "translate")) return false;
  if (!seeChar(p, '(')) return false;
  if (!seeWord(p, "rect")) return false;
  if (!seeInt(p, &x0)) return false;
  if (!seeInt(p, &y0)) return false;
  if (!seeInt(p, &x1)) return false;
  if (!seeInt(p, &y1)) return false;
  if (!seeChar(p, ')')) return false;
  if (!seeInt(p, &dx)) return false;
  if (!seeInt(p, &dy)) return false;
  if (!seeChar(p, ')')) return false;
  return true;
}

如果您有许多“(translate (rect ...”)副本,只需一遍又一遍地调用解析例程,直到它返回 false。

Well, this might be a little old-fashioned, but it's simple and there's nothing faster.

void scanWhite(char*& p){
  while(*p==' ') p++;
}

bool seeInt(char*& p, int& num){
  scanWhite(p);
  char* p1 = p;
  bool bNegative = false;
  if (*p=='-'){bNegative = true; p++;)
  if (!isdigit(*p){p = p1; return false;}
  num = 0;
  while(isdigit(*p)){
    num *= 10;
    num += (*p - '0');
    p++;
  }
  if (bNegative) num = - num;
  return true;
}

bool seeWord(char*& p, char* word){
  scanWhite(p);
  int len = strlen(word);
  if (strncmp(p, word, len)==0 && !isalphanumeric(p[len])){
    p += len;
    return true;
  }
  else return false;
}

bool seeChar(char*& p, char c){
  scanWhite(p);
  if (*p != c) return false;
  p++;
  return true;
}

bool parseTranslateRect(char*& p
  , int& x0, int& y0, int& x1, int& y1
  , int& dx, int& dy
  )
{
  if (!seeChar(p, '(')) return false;
  if (!seeWord(p, "translate")) return false;
  if (!seeChar(p, '(')) return false;
  if (!seeWord(p, "rect")) return false;
  if (!seeInt(p, &x0)) return false;
  if (!seeInt(p, &y0)) return false;
  if (!seeInt(p, &x1)) return false;
  if (!seeInt(p, &y1)) return false;
  if (!seeChar(p, ')')) return false;
  if (!seeInt(p, &dx)) return false;
  if (!seeInt(p, &dy)) return false;
  if (!seeChar(p, ')')) return false;
  return true;
}

If you've got many copies of "(translate (rect ...", just call the parse routine over and over until it returns false.

笑梦风尘 2024-11-17 04:04:09

以下是如何使用 AXE 库 编写此 C++ 解析器:

Rect r;
auto rect = "(rect " 
    & r_decimal(r.left) & space 
    & r_decimal(r.top) & space
    & r_decimal(r.right) & space
    & r_decimal(r.bottom) & space
    & ')';

Point t;
auto translate = "translate " & rect 
    & space & r_decimal(t.x) 
    & space & r_decimal(t.y);
// test it
std::string str("translate (rect 10 10 10 10) 50 50");
auto match = translate(str.begin(), str.end());

这将解析单个翻译PS文件中的声明。如果您需要解析所有翻译语句并且不介意为 postscript 格式编写完整的解析器,则可以使用 *r_find(translate) 规则来跳过您不关心的输入。 r_find(R) 规则搜索输入,直到找到规则 R。现在这非常简单,而且它还会生成非常快的代码,可能比使用“if”-s 和“else”-s 手写的代码更快。

免责声明:我没有测试上面的代码,因此可能会出现小错误。

Here is how you can write this C++ parser using AXE library:

Rect r;
auto rect = "(rect " 
    & r_decimal(r.left) & space 
    & r_decimal(r.top) & space
    & r_decimal(r.right) & space
    & r_decimal(r.bottom) & space
    & ')';

Point t;
auto translate = "translate " & rect 
    & space & r_decimal(t.x) 
    & space & r_decimal(t.y);
// test it
std::string str("translate (rect 10 10 10 10) 50 50");
auto match = translate(str.begin(), str.end());

That will parse a single translate statement in PS file. If you need to parse all translate statements and don't care to write a full blown parser for postscript format, you can use *r_find(translate) rule to skip input that you don't care about. r_find(R) rule searches the input until the rule R is found. Now that's pretty easy and it will also generate very fast code, probably faster than hand-written with "if"-s and "else"-s.

Disclaimer: I din't test the code above, so minor errors are possible.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文