【问题标题】:How can I parse C switch-case and for Statement in AWK?如何在 AWK 中解析 C switch-case 和 for 语句?
【发布时间】:2013-07-16 06:47:15
【问题描述】:

如何使用 awk 解析如下 switch-case 语句?我想用 awk 创建简单的 C 语法检查器。该检查器必须读取代码并返回是否存在语法错误。如果有,awk 应该在上面打印什么错误。

switch(number)
{
    case 1  : number = 'a'; break;
    case 2  : number = 'b'; break;
    default : number = 'x'; 
}

而对于for()语句,像这样:

for(i=0;i<10;i++) 
    {
        number = 'A';
    }

我当前的 switch-case 语句代码是:

#parser_switchcase.awk
{
for(i=1; i<=NF; i++)
{
  if($i~/switch\([[:alnum:]]+\)/)
    print("switch(VALID_VARIABLE)")
}

}

上面我的第一个 C switch-case 代码的结果:

master@master:~/Dokumen/Root$ awk -f parser_switchcase.awk soalswitch 
switch(VALID_VARIABLE)

但它确实需要很多改进。不完整。

我需要 awk 建议来阅读和检查我在上面输入的代码示例。没错,所以我只需要 awk 解析这些代码,而不是附加功能、附加代码等外部可能性,只需要上面代码中提到的。

【问题讨论】:

  • 我怀疑 awk 是否是执行此操作的正确工具...
  • 不要这样做,使用现有的编译器。
  • 您能否更具体地说明您想要完成的任务?对于上述输入,您希望得到什么输出?那么即使我也没有看到这个项目的意义,我也许可以帮助你(但我想你有你的理由)。
  • 要了解在 awk 中为编程语言解析 DSL 需要什么,请查看 awklisp,它是 source

标签: c parsing for-loop awk switch-statement


【解决方案1】:

使用 awk 进行 C 语法检查是一个勇敢的项目。

我会使用gcc 进行语法检查。试试这个:

gcc -fsyntax-only test.c

【讨论】:

  • 但我想为 C 创建新的编译器(当然简单,不如 gcc 复杂)。这就是我需要 awk 建议的原因。我的需求不是太严格,就是上面的switch-case & for code出现的样子。
  • 我没有在 awk 中制作 C 编译器的专业知识,甚至不是一个简单的编译器。但是,如果您有这种专业知识,那当然是可能的。你以前看过yaccbison 吗?我会使用它们。
  • 出于一个重要原因,我必须使用 awk 而不是其他。好的,但谢谢你的建议。
  • 也许你应该先用yacc和bison来做。只是为了看看它是如何工作的......然后,在下一步中,在 awk 中创建一个标记器,它提供另一个 awk 实例,即解析器。这就是我将如何进入这个
【解决方案2】:

正如其他人所建议的那样,awk 不是这项工作的正确工具...
但是,如果您可以保证您的代码符合相当严格和精确的结构,例如问题中提出的结构,您可以为它编写一个非常基本的awk 解释器。

例如:

BEGIN {
  ERROR = "ERROR: ";
  WARNING = "WARNING: ";
}

# Start of switch statment
/switch/ { 
  # Cursory check for valid variable name: must start with a letter or underscore,
  # and be composed of alphanumeric characters or underscores.
  if ($0 !~ /switch\([A-Za-z_]+[A-Za-z0-9_]*\)/)
    print ERROR "switch statement '" $0 "' has a syntax error.";

  switch_stmnt = 1;
  next;
}

# Start of for statement
/for/ {
  # For loop can have lots of various stuff between parentheses, so hard to check.
  # But, if you know it will always be `(i=0;i<10;i++)`, then it's much easier to 
  # create a rule.
  if ($0 !~ /for\(.*;.*;.*\)/)
    print ERROR "for statement '" $0 "' has a syntax error.";

  for_stmnt = 1;
  next;
}

# Start of case statement
/case/ { 
  # Check if in switch
  if (! switch_stmnt)
    print ERROR "case statement '" $0 "' outside of switch statement.";

  # Already in a case statement
  if (case_stmnt)
    print WARNING "case statement fall-through.";

  # Check syntax
  if ($2 !~ /[A-Za-z0-9_]+/ || $3 != ":")
    print ERROR "case statement '" $0 "' has a syntax error.";

  case_stmnt = 1;
}

# Default
/default/ {
  # Check if in switch
  if (! switch_stmnt)
    print ERROR "default statement '" $0 "' outside of switch statement.";

  # Already in a case statement
  if (case_stmnt)
    print WARNING "case statement fall-through.";
}

# Break
/break;/ {
  if (case_stmnt) { case_stmnt = 0; }
  else if (for_stmnt) { }
  else { print ERROR "'break' outside of case statement or for loop."; }
}

# Start of control structure
/{/ { ++brace; }

# End of control structure
/}/ {
  if (switch_stmnt) {
    switch_stmnt = 0;
    case_stmnt = 0;
  }
  else if (for_stmnt)
    for_stmnt = 0;

  if (brace == 0)
    print ERROR "Extra closing brace '}' with no matching open brace.";

  --brace;
}

{
  # Do syntax checking on regular lines, eg. "number = 'a';"
  next;
}

END {
  if (switch_stmnt || for_stmnt || brace)
    print ERROR "Unterminated for or switch statement at end of file.";
}

这会检查一些语句是否符合一些规则。您可以使用更多的正则表达式规则和标志来扩展它。特别困难的是没有关键字的普通语句,因为这些可能是声明、赋值、函数调用等。但是,如果您只像上面那样进行number = 'a'; 之类的赋值,那么匹配这些行也不难(类似/[A-Za-z_]+[A-Za-z0-9_]* = '.'/)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 2014-06-13
    • 2014-08-05
    相关资源
    最近更新 更多