簡體   English   中英

go工具yacc中最簡單的解析器

[英]Simplest of parsers in go tool yacc

使用這個命令:

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

嘗試構建這個 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})
}

錯誤: bad syntax on first rule: boilerplate.y:16錯誤: bad syntax on first rule: boilerplate.y:16

成功地讓這個例子工作:

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

嘗試構建我自己的並通過 lex & yacc 書工作。 資源似乎僅限於不存在。

您的規格中有不正確的rule

規范文件具有以下聲明:

declarations
%%
rules
%%
programs

rule定義為:

A  :  BODY  ;

其中A是非終端符號,而BODY由令牌(終端符號),非終端和文字組成。 :; 是規則聲明語法的必需組件。

因此規則:

.|\n   ECHO;

在語法上是不正確的。

由於您只是嘗試回顯輸入, calc.y將基於calc.y進行非常簡單的實現(文件echo.y ):

規則

%%

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

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

程序

%%

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
}

要編譯並運行此程序,請在命令提示符處執行以下操作:

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

如您所見,您必須在Lex方法中定義自己的解析規則。 struct InputLex用於在解析輸入時保存值。 InputSymType是自動生成的,由規范的declaration部分中declaration%union定義。

據我所知,沒有辦法直接使用JISON或正則表達式使用go的yacc工具進行匹配。 您可能需要查看其他一些庫。

更多細節可以在這里找到: http//dinosaur.compilertools.net/yacc/

完整的工作代碼: https//play.golang.org/p/u1QxwRKLCl

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM