简体   繁体   English

go工具yacc中最简单的解析器

[英]Simplest of parsers in go tool yacc

Using this command:使用这个命令:

go tool yacc -p Verb -o verb.go boilerplate.y

Trying to build this yacc file:尝试构建这个 yacc 文件:

// boilerplate.y
%{

package main

import (
    "bufio"
    "fmt"
    "os"
    "unicode"
)

%}

%% 

.|\n   ECHO;

%%

func main() {
    fi := bufio.NewReader(os.NewFile(0, "stdin"))
  s, err := fi.ReadString('\n')
  if err != nil {
    fmt.Println('error', err)
  } 

  VerbParse(&VerbLex{s: s})
}

Error: bad syntax on first rule: boilerplate.y:16错误: bad syntax on first rule: boilerplate.y:16错误: bad syntax on first rule: boilerplate.y:16

Successfully got this example to work:成功地让这个例子工作:

https://github.com/golang-samples/yacc/blob/master/simple/calc.y https://github.com/golang-samples/yacc/blob/master/simple/calc.y

Trying to build my own and work through the lex & yacc book.尝试构建我自己的并通过 lex & yacc 书工作。 Resources seem limited to non existent.资源似乎仅限于不存在。

You have an incorrect rule in your specifications. 您的规格中有不正确的rule

A specification file has the following declaration: 规范文件具有以下声明:

declarations
%%
rules
%%
programs

Where a rule is defined as: rule定义为:

A  :  BODY  ;

Where A is a non-terminal symbol, while BODY is made up of tokens (terminal symbols), non-terminals and literals. 其中A是非终端符号,而BODY由令牌(终端符号),非终端和文字组成。 The : and ; :; are required components of rule declaration syntax. 是规则声明语法的必需组件。

Hence the rule: 因此规则:

.|\n   ECHO;

is syntactically incorrect. 在语法上是不正确的。

Since you are simply trying to echo the input, a very simple implementation based on calc.y would be following (file echo.y ): 由于您只是尝试回显输入, calc.y将基于calc.y进行非常简单的实现(文件echo.y ):

rules 规则

%%

in : /* empty */
  | in input '\n'
     { fmt.Printf("Read character: %s\n", $2) }
  ;

input : CHARACTER
  | input CHARACTER
      { $$ = $1 + $2 }
  ;

program 程序

%%

type InputLex struct {
    // contains one complete input string (with the trailing \n)
    s string
    // used to keep track of parser position along the above imput string
    pos int
}

func (l *InputLex) Lex(lval *InputSymType) int {
    var c rune = ' '

    // skip through all the spaces, both at the ends and in between
    for c == ' ' {
        if l.pos == len(l.s) {
            return 0
        }
        c = rune(l.s[l.pos])
        l.pos += 1
    }

    // only look for input characters that are either digits or lower case
    // to do more specific parsing, you'll define more tokens and have a 
    // more complex parsing logic here, choosing which token to return
    // based on parsed input
    if unicode.IsDigit(c) || unicode.IsLower(c) {
        lval.val = string(c)
        return CHARACTER
    }

    // do not return any token in case of unrecognized grammer
    // this results in syntax error
    return int(c)
}

func (l *InputLex) Error(s string) {
    fmt.Printf("syntax error: %s\n", s)
}

func main() {
    // same as in calc.y
}

func readline(fi *bufio.Reader) (string, bool) {
    // same as in calc.y
}

To compile and run this program, do the following at command prompt: 要编译并运行此程序,请在命令提示符处执行以下操作:

go tool yacc -o echo.go -p Input echo.y
go run echo.go

As you can see, you'll have to define your own parsing rules in the Lex method. 如您所见,您必须在Lex方法中定义自己的解析规则。 The struct InputLex is designed to hold the values while your input is being parsed. struct InputLex用于在解析输入时保存值。 InputSymType is auto generated and is defined by the %union declared in the declaration part of specification. InputSymType是自动生成的,由规范的declaration部分中declaration%union定义。

As far as I can tell, there is no way to directly use JISON or a regex to do the matching using go's yacc tool. 据我所知,没有办法直接使用JISON或正则表达式使用go的yacc工具进行匹配。 You may have to take a look at some other libraries. 您可能需要查看其他一些库。

More details can be found here: http://dinosaur.compilertools.net/yacc/ 更多细节可以在这里找到: http//dinosaur.compilertools.net/yacc/

Full working code here: https://play.golang.org/p/u1QxwRKLCl 完整的工作代码: https//play.golang.org/p/u1QxwRKLCl

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM