• 自制编译器 青木峰郎 笔记 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

  • 相关阅读:
    linux下编译安装mysql
    Linux系统信息查看命令(转载)
    python使用memcached
    ./configure 命令使用和参数解析
    linux平台下使用 nginx + spawn-cgi 部署webpy程序
    冒泡排序
    在gitub上添加ssh key
    给p标签做单行省略 设置宽度的问题
    移动端的无缝滚动
    canvas-图片翻转
  • 原文地址:https://www.cnblogs.com/xuesu/p/14377215.html
Copyright © 2020-2023  润新知