自制编译器 青木峰郎 笔记 Ch3 词法分析的概要

3.1 语法分析的概要

解析器往往会跳过分号和括号等没有必要保存的元素,所以parser一般生成的语法树已经不再严格对应代码本身

3.2 解析器生成器

常用的解析器一般使用LR, LALR和LL文法。速度上: LL>LALR>LR,解析范围上: LL<LALR<LR。目前最主流的是LALR(yacc),本文使用LL文法(javacc)

软件名 能生成的语言 可处理的文法范围(能超前读取的token个数)
antlr java,c,c++,go,js等 LL(*)
javacc java LL(k)
jay java LALR(1)
yacc C LALR(1)
bison C LALR(1)
kmyacc C,java,js,perl LALR(1)
Lemon C LALR(1)
Racc Ruby LALR(1)
Parsec Haskell LL(k)

3.3 javacc

基本使用方法javacc xxx.jj
e.g:

options{
    static = false;

}
//BasicParser: ParserName
PARSER_BEGIN(BasicParser)
import java.io.*;
class BasicParser{
    static public void main(String[] args){
        for(String arg:args){
            try{
                System.out.println(arg);
                System.out.println(evaluate(arg));
            }
            catch(ParseException ex){
                ex.printStackTrace();
            }
        }
    }
    static public long evaluate(String src) throws ParseException{
        Reader reader = new StringReader(src);
        return new BasicParser(reader).expr();
    }
}
PARSER_END(BasicParser)

SKIP: { <[" ", "	", "
", "
"]> }
TOKEN: {
    <INT: (["0"-"9"])+>
}
long expr():
{
    Token x,y;
}
{
	LOOKAHEAD(2)
    x=<INT> "+" y=<INT> <EOF>{
        return Long.parseLong(x.image) + Long.parseLong(y.image);
    } |
	LOOKAHEAD(2)
    x=<INT> "-" y=<INT> <EOF>{
        return Long.parseLong(x.image) - Long.parseLong(y.image);
    } |
	LOOKAHEAD(2)
    x=<INT> "*" y=<INT> <EOF>{
        return Long.parseLong(x.image) * Long.parseLong(y.image);
    } |
	LOOKAHEAD(2)
    x=<INT> "/" y=<INT> <EOF>{
        return Long.parseLong(x.image) / Long.parseLong(y.image);
    }
}

jj基本格式一般是:

//jj选项
options{
      STATIC=false;
      DEBUG_PARSER=true;
      UNICODE_INPUT=true;
      JDK_VERSION="1.5"
}
//Parser附加代码
PARSER_BEGIN(Example)

/** Simple brace matcher. */
public class Example {

  /** Main entry point. */
  public static void main(String args[]) throws ParseException {
    Example parser = new Example(System.in);
    parser.Input();
  }

}

PARSER_END(Example)
//Scanner描述

SKIP: { <[" ", "	", "
", "
"]> }
//Parser描述
/** Root production. */
void Input() :
{}
{
  MatchedBraces() ("
"|"
")* <EOF>
}

/** Brace matching production. */
void MatchedBraces() :
{}
{
  "{" [ MatchedBraces() ] "}"
}

中文处理

必须要把Unicode_input模式设置为true

原文地址:https://www.cnblogs.com/xuesu/p/14377215.html