Changeset 5206


Ignore:
Timestamp:
Nov 7, 2016, 3:54:09 PM (13 months ago)
Author:
xwa163
Message:
  1. Extend Regex Syntax, include: (a) RL2.6 of UTS#18, support regex in property value. e.g. \p{script=/.*hir.*/} (b) Support syntax of property expression when parsing boundary. e.g. \b{greek} (c) Extend property expression in non capture group. e.g. (?\p{upper}:\p{greek}\p{script=hira})
  2. Add related test cases
Location:
icGREP/icgrep-devel
Files:
1 added
16 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/QA/greptest.xml

    r5164 r5206  
    799799ن‍ 
    800800</datafile>
     801
    801802<grepcase regexp="^\X$" datafile="graphemebreaktest" grepcount="55"/>
    802803<!--<grepcase regexp="^\X\X$" datafile="graphemebreaktest" grepcount="153"/>
     
    810811<grepcase regexp="\B{g}\x{308}" datafile="graphemebreaktest" grepcount="100"/>
    811812
     813<datafile id="hira_border">aa ba ca
     814&#x3096;&#x309d;&#x002d;&#x3088;&#x308a;a
     815&#x3096;a
     816&#x3096; &#x3096;
     817</datafile>
     818<datafile id="hiragana_and_katakana">&#x3042;&#x3044;
     819&#x3046;&#x3048;
     820&#x304a;
     821&#x30a2;&#x30a4;
     822&#x30a6;&#x30a8;&#x30aa;
     823</datafile>
     824<datafile id="upper_lower_greek">&#x0391;&#x03b1;&#x0392;&#x03b2;&#x0393;&#x03b3;
     825&#x0391;&#x0392;&#x0393;
     826&#x03b1;&#x03b2;&#x03b3;
     827</datafile>
     828
     829<grepcase regexp="\b{script=hira}a" datafile="hira_border" grepcount="2"/>
     830<grepcase regexp="\b{script=hira}" datafile="hira_border" grepcount="3"/>
     831<grepcase regexp="\p{script=/hir./}" datafile="hira_border" grepcount="3"/>
     832<grepcase regexp="\p{script=/.*hir.*/}" datafile="hira_border" grepcount="3"/>
     833<grepcase regexp="\p{script=/hir.gana/}" datafile="hiragana_and_katakana" grepcount="3"/>
     834<grepcase regexp="\p{script=/kat.kana/}" datafile="hiragana_and_katakana" grepcount="2"/>
     835<grepcase regexp="\p{script=/(kata|Hira).ana/}" datafile="hiragana_and_katakana" grepcount="5"/>
     836
     837<grepcase regexp="(?:\p{greek}\p{greek}\p{greek})" datafile="upper_lower_greek" grepcount="3"/>
     838<grepcase regexp="(?\p{upper}:\p{greek}\p{greek}\p{greek})" datafile="upper_lower_greek" grepcount="1"/>
     839<grepcase regexp="(?\p{lower}:\p{greek}\p{greek}\p{greek})" datafile="upper_lower_greek" grepcount="1"/>
     840<grepcase regexp="(?\p{upper}:\p{greek})" datafile="upper_lower_greek" grepcount="2"/>
     841
    812842<grepcase regexp="\N{AIRPLANE}" datafile="../All_good" grepcount="8"/>
     843
    813844</greptest>
  • icGREP/icgrep-devel/icgrep/UCD/PropertyObjects.cpp

    r5159 r5206  
    3030int PropertyObject::GetPropertyValueEnumCode(const std::string & value_spec) {
    3131    throw std::runtime_error("Property " + value_spec + " unsupported.");
     32}
     33const std::string& PropertyObject::GetPropertyValueGrepString() {
     34    throw std::runtime_error("Property Value Grep String unsupported.");
    3235}
    3336
     
    7376};
    7477
    75    
     78const std::string& EnumeratedPropertyObject::GetPropertyValueGrepString() {
     79    if (!property_value_grep_string.size()) {
     80        for (unsigned i = 0; i != property_value_full_names.size(); i++) {
     81            property_value_grep_string += canonicalize_value_name(property_value_full_names[i]) + "\n";
     82        }
     83        for (unsigned i = 0; i != property_value_enum_names.size(); i++) {
     84            property_value_grep_string += canonicalize_value_name(property_value_enum_names[i]) + "\n";
     85        }
     86    }
     87    return property_value_grep_string;
     88}
     89
    7690int EnumeratedPropertyObject::GetPropertyValueEnumCode(const std::string & value_spec) {
    7791    // The canonical full names are not stored in the precomputed alias map,
     
    123137}
    124138
     139const std::string& ExtensionPropertyObject::GetPropertyValueGrepString() {
     140    return property_object_table[base_property]->GetPropertyValueGrepString();
     141}
     142
    125143const UnicodeSet & BinaryPropertyObject::GetCodepointSet(const std::string & value_spec) {
    126144    int property_enum_val = Binary_ns::Y;
     
    146164}
    147165
     166const std::string& BinaryPropertyObject::GetPropertyValueGrepString() {
     167    if (!property_value_grep_string.size()) {
     168        for (auto iter = Binary_ns::aliases_only_map.begin(), end = Binary_ns::aliases_only_map.end(); iter != end; ++iter) {
     169            property_value_grep_string += iter->first + "\n";
     170        }
     171    }
     172    return property_value_grep_string;
    148173}
     174
     175}
  • icGREP/icgrep-devel/icgrep/UCD/PropertyObjects.h

    r5159 r5206  
    4141    PropertyObject(property_t p, ClassTypeId k) : the_property(p), the_kind(k) {}
    4242    virtual int GetPropertyValueEnumCode(const std::string & value_spec);
     43    virtual const std::string& GetPropertyValueGrepString();
    4344    property_t the_property;
    4445    ClassTypeId the_kind;
     
    8889
    8990    virtual int GetPropertyValueEnumCode(const std::string & value_spec);
     91    virtual const std::string& GetPropertyValueGrepString();
    9092    const UnicodeSet & GetCodepointSet(const std::string & value_spec);
    9193    const UnicodeSet & GetCodepointSet(const int property_enum_val) const;
     
    107109    const std::vector<std::string> & property_value_full_names;  // never changes
    108110    std::unordered_map<std::string, int> & property_value_aliases;
     111    std::string property_value_grep_string;
    109112    bool uninitialized; // full names must be added dynamically.
    110113    const std::vector<const UnicodeSet *> property_value_sets;
     
    136139
    137140    virtual int GetPropertyValueEnumCode(const std::string & value_spec);
     141    virtual const std::string& GetPropertyValueGrepString();
    138142    const UnicodeSet & GetCodepointSet(const std::string & value_spec);
    139143    const UnicodeSet & GetCodepointSet(const int property_enum_val) const;
     
    161165    const UnicodeSet & GetCodepointSet(const std::string & value_spec);
    162166    const UnicodeSet & GetCodepointSet(const int property_enum_val);
     167    virtual const std::string& GetPropertyValueGrepString();
    163168private:
    164169    bool mNoUninitialized;
    165170    UnicodeSet mY;
    166171    UnicodeSet mN;
     172    std::string property_value_grep_string;
    167173};
    168174
  • icGREP/icgrep-devel/icgrep/UCD/resolve_properties.cpp

    r5091 r5206  
    220220}
    221221
     222const std::string& getPropertyValueGrepString(const std::string & prop) {
     223    auto propName = canonicalize_value_name(prop);
     224    auto propit = alias_map.find(propName);
     225    if (propit == alias_map.end()) {
     226        throw UnicodePropertyExpressionError("Expected a property name, but '" + prop + "' found instead");
     227    }
     228    auto theprop = propit->second;
     229    if (EnumeratedPropertyObject * p = dyn_cast<EnumeratedPropertyObject>(property_object_table[theprop])){
     230        return p->GetPropertyValueGrepString();
     231    } else if (BinaryPropertyObject * p = dyn_cast<BinaryPropertyObject>(property_object_table[theprop])) {
     232        return p->GetPropertyValueGrepString();
     233    }
     234
     235    throw UnicodePropertyExpressionError("Property " + property_full_name[theprop] + " recognized but not supported in icgrep 1.0");
     236}
     237
    222238UnicodeSet resolveUnicodeSet(Name * const name) {
    223239    if (name->getType() == Name::Type::UnicodeProperty) {
  • icGREP/icgrep-devel/icgrep/UCD/resolve_properties.h

    r5091 r5206  
    2525std::string resolvePropertyFunction(re::Name * const property);
    2626UCD::UnicodeSet resolveUnicodeSet(re::Name * const name);
     27const std::string& getPropertyValueGrepString(const std::string & prop);
    2728
    2829}
  • icGREP/icgrep-devel/icgrep/UCD/ucd_compiler.cpp

    r5202 r5206  
    66#include <utf16_encoder.h>
    77#include <iostream>
     8#include <array>
    89
    910using namespace cc;
  • icGREP/icgrep-devel/icgrep/grep_engine.cpp

    r5204 r5206  
    2525#include <llvm/IR/TypeBuilder.h>
    2626#include <UCD/UnicodeNameData.h>
     27#include <UCD/resolve_properties.h>
    2728
    2829
     
    198199}
    199200
    200 Function * generateCPUKernel(Module * m, IDISA::IDISA_Builder * iBuilder, bool isNameExpression){
     201Function * generateCPUKernel(Module * m, IDISA::IDISA_Builder * iBuilder, GrepType grepType){
    201202    Type * const size_ty = iBuilder->getSizeTy();
    202203    Type * const int8PtrTy = iBuilder->getInt8PtrTy();
     
    219220    MatchResults.setStreamSetBuffer(rsltStream, fileSize);
    220221
    221     kernel::ScanMatchKernel scanMatchK(iBuilder, isNameExpression);
     222    kernel::ScanMatchKernel scanMatchK(iBuilder, grepType);
    222223    scanMatchK.generateKernel({&MatchResults}, {});
    223224           
     
    230231}
    231232
    232 void GrepEngine::grepCodeGen(std::string moduleName, re::RE * re_ast, bool CountOnly, bool UTF_16, bool isNameExpression) {
     233void GrepEngine::grepCodeGen(std::string moduleName, re::RE * re_ast, bool CountOnly, bool UTF_16, GrepType grepType) {
    233234    isUTF_16 = UTF_16;
    234235    int addrSpace = 0;
     
    269270    unsigned encodingBits = UTF_16 ? 16 : 8;
    270271
    271     mIsNameExpression = isNameExpression;
     272    mGrepType = grepType;
    272273
    273274    Type * const int32ty = iBuilder->getInt32Ty();
     
    402403            Value * icgrepInstance = icgrepK.createInstance({});
    403404
    404             kernel::ScanMatchKernel scanMatchK(iBuilder, mIsNameExpression);
     405            kernel::ScanMatchKernel scanMatchK(iBuilder, mGrepType);
    405406            scanMatchK.generateKernel({&MatchResults}, {});               
    406407            Value * scanMatchInstance = scanMatchK.createInstance({iBuilder->CreateBitCast(inputStream, int8PtrTy), fileSize, fileIdx});
     
    431432   
    432433        Compile2PTX(M, IRFilename, PTXFilename);
    433         mainCPUFn = generateCPUKernel(cpuM, CPUBuilder, mIsNameExpression);
     434        mainCPUFn = generateCPUKernel(cpuM, CPUBuilder, mGrepType);
    434435        if (CountOnly) return;
    435436    }
     
    472473
    473474    return getParsedCodePointSet();
     475}
     476
     477const std::vector<std::string> & GrepEngine::grepPropertyValues(const std::string& propertyName) {
     478    setParsedPropertyValues();
     479
     480    std::string str = UCD::getPropertyValueGrepString(propertyName);
     481
     482    //use const_cast to workaround const input
     483    mGrepFunction(const_cast<char*>(str.c_str()), str.size(), 0);
     484
     485    return getParsedProeprtyValues();
    474486}
    475487
     
    607619
    608620
     621std::vector<std::string> parsedPropertyValues;
     622
     623extern "C" {
     624    void insert_property_values(size_t lineNum, size_t line_start, size_t line_end, const char * buffer) {
     625        auto result = std::string(buffer + line_start, buffer + line_end);
     626        parsedPropertyValues.push_back(result);
     627    }
     628}
     629
     630inline void setParsedPropertyValues() {
     631    parsedPropertyValues.clear();
     632}
     633
     634inline const std::vector<std::string>& getParsedProeprtyValues() {
     635    return parsedPropertyValues;
     636}
     637
     638
    609639void icgrep_Linking(Module * m, ExecutionEngine * e) {
    610640    Module::FunctionListType & fns = m->getFunctionList();
     
    621651            e->addGlobalMapping(cast<GlobalValue>(it), (void *)&insert_codepoints);
    622652        }
     653        if (fnName == "insert_property_values") {
     654            e->addGlobalMapping(cast<GlobalValue>(it), (void *)&insert_property_values);
     655        }
    623656#ifndef DISABLE_PREGENERATED_UCD_FUNCTIONS
    624657        else {
  • icGREP/icgrep-devel/icgrep/grep_engine.h

    r5151 r5206  
    1111#include <re/re_re.h>
    1212#include <llvm/ExecutionEngine/ExecutionEngine.h>
     13#include <grep_type.h>
    1314
    1415
     
    2728    ~GrepEngine();
    2829 
    29     void grepCodeGen(std::string moduleName, re::RE * re_ast, bool CountOnly, bool UTF_16 = false, bool isNameExpression = false);
     30    void grepCodeGen(std::string moduleName, re::RE * re_ast, bool CountOnly, bool UTF_16 = false, GrepType grepType = GrepType::Normal);
    3031   
    3132    void doGrep(const std::string & fileName, const int fileIdx, bool CountOnly, std::vector<size_t> &total_CountOnly, bool UTF_16);
    3233   
    3334    re::CC *  grepCodepoints();
     35    const std::vector<std::string> & grepPropertyValues(const std::string& propertyName);
    3436   
    3537private:
     
    3941    GrepFunctionType_CPU mGrepFunction_CPU;
    4042
    41     bool mIsNameExpression;
     43    GrepType mGrepType;
    4244    llvm::ExecutionEngine * mEngine;
    4345};
     
    4951void setParsedCodePointSet();
    5052
     53const std::vector<std::string>& getParsedProeprtyValues();
     54void setParsedPropertyValues();
     55
     56
    5157void initResult(std::vector<std::string> filenames);
    5258void PrintResult(bool CountOnly, std::vector<size_t> & total_CountOnly);
  • icGREP/icgrep-devel/icgrep/kernels/scanmatchgen.cpp

    r5204 r5206  
    120120   
    121121    Constant * matchProcessor;
    122     if (mIsNameExpression) {
    123         matchProcessor = m->getOrInsertFunction("insert_codepoints", Type::getVoidTy(ctxt), T, T, T, S, nullptr);
    124     } else {
    125         matchProcessor = m->getOrInsertFunction("wrapped_report_match", Type::getVoidTy(ctxt), T, T, T, S, T, T, nullptr);
     122    switch (mGrepType) {
     123        case GrepType::Normal:
     124            matchProcessor = m->getOrInsertFunction("wrapped_report_match", Type::getVoidTy(ctxt), T, T, T, S, T, T, nullptr);
     125            break;
     126        case GrepType::NameExpression:
     127            matchProcessor = m->getOrInsertFunction("insert_codepoints", Type::getVoidTy(ctxt), T, T, T, S, nullptr);
     128            break;
     129        case GrepType::PropertyValue:
     130            matchProcessor = m->getOrInsertFunction("insert_property_values", Type::getVoidTy(ctxt), T, T, T, S, nullptr);
     131            break;
     132
    126133    }
    127134    iBuilder->SetInsertPoint(BasicBlock::Create(ctxt, "entry", function,0));
     
    194201
    195202    Value * fileBuf = getScalarField(instance, "FileBuf");
    196     if (mIsNameExpression) {
    197         iBuilder->CreateCall(matchProcessor, std::vector<Value *>({matchRecordNum_phi, matchRecordStart_phi, matchRecordEnd, fileBuf}));
    198     } else {
    199         Value * fileSize = getScalarField(instance, "FileSize");
    200         Value * fileIdx = getScalarField(instance, "FileIdx");
    201         iBuilder->CreateCall(matchProcessor, std::vector<Value *>({matchRecordNum_phi, matchRecordStart_phi, matchRecordEnd, fileBuf, fileSize, fileIdx}));
     203    switch (mGrepType) {
     204        case GrepType::Normal:
     205        {
     206            Value * fileSize = getScalarField(instance, "FileSize");
     207            Value * fileIdx = getScalarField(instance, "FileIdx");
     208            iBuilder->CreateCall(matchProcessor, std::vector<Value *>({matchRecordNum_phi, matchRecordStart_phi, matchRecordEnd, fileBuf, fileSize, fileIdx}));
     209            break;
     210        }
     211        case GrepType::NameExpression:
     212        case GrepType::PropertyValue:
     213            iBuilder->CreateCall(matchProcessor, std::vector<Value *>({matchRecordNum_phi, matchRecordStart_phi, matchRecordEnd, fileBuf}));
     214            break;
    202215    }
    203216   
  • icGREP/icgrep-devel/icgrep/kernels/scanmatchgen.h

    r5204 r5206  
    88#include "streamset.h"
    99#include "kernel.h"
     10#include "grep_type.h"
    1011#include <llvm/Support/Host.h>
    1112#include <llvm/ADT/Triple.h>
     
    1920class ScanMatchKernel : public KernelBuilder {
    2021public:
    21     ScanMatchKernel(IDISA::IDISA_Builder * iBuilder, bool isNameExpression) :
     22    ScanMatchKernel(IDISA::IDISA_Builder * iBuilder, GrepType grepType) :
    2223    KernelBuilder(iBuilder, "scanMatch",
    2324                  {Binding{parabix::StreamSetType(iBuilder,2, 1), "matchResults"}},
     
    2728                    {Binding{iBuilder->getSizeTy(), "BlockNo"}, Binding{iBuilder->getSizeTy(), "LineStart"}, Binding{iBuilder->getSizeTy(), "LineNum"}}),
    2829
    29     mIsNameExpression(isNameExpression) {}
     30    mGrepType(grepType) {}
    3031       
    3132private:
     
    3334    llvm::Function * generateScanWordRoutine(llvm::Module * m);
    3435       
    35     bool mIsNameExpression;
     36    GrepType mGrepType;
    3637};
    3738}
  • icGREP/icgrep-devel/icgrep/re/re_parser.cpp

    r5182 r5206  
    6868    , mCursor(regular_expression)
    6969    , mCaptureGroupCount(0)
     70    , mReSyntax(RE_Syntax::PCRE)
    7071    {
    7172
     
    8788
    8889RE * RE_Parser::parse_alt() {
     90    return parse_alt_with_intersect(nullptr);
     91}
     92
     93RE * RE_Parser::parse_alt_with_intersect(RE* reToBeIntersected) {
    8994    std::vector<RE *> alt;
    9095    for (;;) {
    91         alt.push_back(parse_seq());
     96        alt.push_back(parse_seq_with_intersect(reToBeIntersected));
    9297        if (*mCursor != '|') {
    9398            break;
     
    102107
    103108RE * RE_Parser::parse_seq() {
     109    return parse_seq_with_intersect(nullptr);
     110}
     111
     112RE * RE_Parser::parse_seq_with_intersect(RE* reToBeIntersected) {
    104113    std::vector<RE *> seq;
    105114    for (;;) {
     
    111120            }
    112121            break;
     122        }
     123        if (reToBeIntersected) {
     124            re = makeIntersect(reToBeIntersected, re);
    113125        }
    114126        re = extend_item(re);
     
    250262                    return parse_next_item();
    251263                }
     264            case '\\': {
     265                ++mCursor;
     266                if (*mCursor == 'p' || *mCursor == 'P') {
     267                    RE* reToBeIntersected = parseEscapedSet();
     268                    if (*mCursor == ':') {
     269                        ++mCursor;
     270                        group_expr = parse_alt_with_intersect(reToBeIntersected);
     271                        fModeFlagSet = modeFlagSet;
     272                        break;
     273                    } else {  // if *_cursor == ')'
     274                        ++mCursor;
     275                        return parse_next_item();
     276                    }
     277                }
     278                break;
     279            }
    252280            default:
    253281                ParseFailure("Illegal (? syntax.");
     
    382410                return complemented ? makeWordNonBoundary() : makeWordBoundary();
    383411            } else {
    384                 switch (*++mCursor) {
    385                     case 'g':
    386                         re = complemented ? makeZeroWidth("NonGCB") : makeZeroWidth("GCB");
    387                         break;
    388                     case 'w': ParseFailure("\\b{w} not yet supported.");
    389                     case 'l': ParseFailure("\\b{l} not yet supported.");
    390                     case 's': ParseFailure("\\b{s} not yet supported.");
    391                     default: ParseFailure("Unrecognized boundary assertion");
    392                 }
    393                 if (*++mCursor != '}') {
    394                     ParseFailure("Malformed boundary assertion");
    395                 }
    396                 ++mCursor;
     412                ++mCursor;
     413                if (isCharAhead('}')) {
     414                    switch (*mCursor) {
     415                        case 'g':
     416                            re = complemented ? makeZeroWidth("NonGCB") : makeZeroWidth("GCB");
     417                            ++mCursor;
     418                            ++mCursor;
     419                            break;
     420                        case 'w': ParseFailure("\\b{w} not yet supported.");
     421                        case 'l': ParseFailure("\\b{l} not yet supported.");
     422                        case 's': ParseFailure("\\b{s} not yet supported.");
     423//                        default: ParseFailure("Unrecognized boundary assertion");
     424                    }
     425                }
     426                if (!re) {
     427                    auto propExpr = parsePropertyExpression();
     428                    if (*mCursor++ != '}') {
     429                        ParseFailure("Malformed boundary assertion");
     430                    }
     431                    re = complemented ? makeReNonBoundary(propExpr) : makeReBoundary(propExpr);
     432                }
    397433                return re;
    398434            }
     
    529565}
    530566
     567bool RE_Parser::isCharAhead(char c) {
     568    if (mCursor.remaining() < 2) {
     569        return false;
     570    }
     571    auto nextCursor = mCursor.pos() + 1;
     572    return *nextCursor == c;
     573}
     574
    531575RE * RE_Parser::parsePropertyExpression() {
    532576    const auto start = mCursor.pos();
     
    543587    }
    544588    if (*mCursor == '=') {
     589        // We have a property-name = value expression
    545590        const auto prop_end = mCursor.pos();
    546591        mCursor++;
    547         const auto val_start = mCursor.pos();
    548         while (mCursor.more()) {
    549             bool done = false;
    550             switch (*mCursor) {
    551                 case '}': case ':':
    552                     done = true;
    553             }
    554             if (done) {
    555                 break;
    556             }
    557             ++mCursor;
    558         }
    559         // We have a property-name = value expression
    560         return createName(canonicalize(start, prop_end), canonicalize(val_start, mCursor.pos()));
     592        auto val_start = mCursor.pos();
     593        if (*val_start != '/') {
     594            // property-value is normal string
     595            while (mCursor.more()) {
     596                bool done = false;
     597                switch (*mCursor) {
     598                    case '}': case ':':
     599                        done = true;
     600                }
     601                if (done) {
     602                    break;
     603                }
     604                ++mCursor;
     605            }
     606            return createName(canonicalize(start, prop_end), canonicalize(val_start, mCursor.pos()));
     607        } else {
     608            // property-value is another regex
     609            auto previous = val_start;
     610            auto current = (++mCursor).pos();
     611            val_start = current;
     612
     613            while (true) {
     614                if (*current == '/' && *previous != '\\') {
     615                    break;
     616                }
     617
     618                if (!mCursor.more()) {
     619                    ParseFailure("Malformed property expression");
     620                }
     621
     622                previous = current;
     623                current = (++mCursor).pos();
     624            }
     625            ++mCursor;
     626            return parseRegexPropertyValue(canonicalize(start, prop_end), canonicalize(val_start, current));
     627        }
    561628    }
    562629    return createName(canonicalize(start, mCursor.pos()));
     630}
     631
     632RE * RE_Parser::parseRegexPropertyValue(const std::string& propName, const std::string& regexValue) {
     633    auto regexValueForGrep = "^" + regexValue + "$";
     634    RE* propValueRe = RE_Parser::parse(regexValueForGrep, fModeFlagSet, mReSyntax);
     635    GrepEngine engine;
     636    engine.grepCodeGen("NamePattern", propValueRe, false, false, GrepType::PropertyValue);
     637    auto grepValue = engine.grepPropertyValues(propName);
     638
     639    auto grepValueSize = grepValue.size();
     640    if (!grepValueSize) {
     641        ParseFailure("regex " + regexValue + " match no property values");
     642    } else if (grepValueSize == 1) {
     643        // handle right value
     644        return createName(std::string(propName), std::string(grepValue[0]));
     645    } else {
     646        std::vector<re::RE*> valueRes;
     647        for (auto iter = grepValue.begin(); iter != grepValue.end(); ++iter) {
     648            valueRes.push_back(createName(std::string(propName), std::string(*iter)));
     649        }
     650
     651        return makeAlt(valueRes.begin(), valueRes.end());
     652    }
    563653}
    564654
     
    581671   
    582672    GrepEngine engine;
    583     engine.grepCodeGen("NamePattern", embedded, false, false, true);
     673    engine.grepCodeGen("NamePattern", embedded, false, false, GrepType::NameExpression);
    584674    CC * codepoints = engine.grepCodepoints();
    585675   
     
    9721062
    9731063           
    974                        
     1064
    9751065                           
    9761066RE * RE_Parser::makeWordBoundary() {
    9771067    Name * wordC = makeWordSet();
    978     return makeAlt({makeSeq({makeNegativeLookBehindAssertion(wordC), makeLookAheadAssertion(wordC)}),
    979                     makeSeq({makeLookBehindAssertion(wordC), makeNegativeLookAheadAssertion(wordC)})});
     1068    return makeReBoundary(wordC);
    9801069}
    9811070
    9821071RE * RE_Parser::makeWordNonBoundary() {
    9831072    Name * wordC = makeWordSet();
    984     return makeAlt({makeSeq({makeNegativeLookBehindAssertion(wordC), makeNegativeLookAheadAssertion(wordC)}),
    985                     makeSeq({makeLookBehindAssertion(wordC), makeLookAheadAssertion(wordC)})});
     1073    return makeReNonBoundary(wordC);
     1074}
     1075
     1076inline RE * RE_Parser::makeReBoundary(RE * re) {
     1077    return makeAlt({makeSeq({makeNegativeLookBehindAssertion(re), makeLookAheadAssertion(re)}),
     1078                    makeSeq({makeLookBehindAssertion(re), makeNegativeLookAheadAssertion(re)})});
     1079}
     1080inline RE * RE_Parser::makeReNonBoundary(RE * re) {
     1081    return makeAlt({makeSeq({makeNegativeLookBehindAssertion(re), makeNegativeLookAheadAssertion(re)}),
     1082                    makeSeq({makeLookBehindAssertion(re), makeLookAheadAssertion(re)})});
    9861083}
    9871084
  • icGREP/icgrep-devel/icgrep/re/re_parser.h

    r5180 r5206  
    119119    virtual RE * parse_RE();
    120120
    121     virtual RE * parse_alt();
     121    RE * parse_alt();
     122
     123    virtual RE * parse_alt_with_intersect(RE* reToBeIntersected);
    122124
    123125    RE * parse_seq();
    124126
     127    RE * parse_seq_with_intersect(RE* reToBeIntersected);
     128
    125129    virtual RE * parse_next_item();
    126130
     
    144148
    145149    virtual RE * parsePropertyExpression();
     150    RE * parseRegexPropertyValue(const std::string& propName, const std::string& regexValue);
    146151
    147152    Name * parseNamePatternExpression();
     
    150155    RE * makeWordBoundary();
    151156    RE * makeWordNonBoundary();
     157    RE * makeReBoundary(RE * wordC);
     158    RE * makeReNonBoundary(RE * wordC);
    152159    RE * makeWordBegin();
    153160    RE * makeWordEnd();
     
    179186
    180187    static std::string canonicalize(const cursor_t begin, const cursor_t end);
     188    bool isCharAhead(char c);
    181189
    182190protected:
     
    190198    NameMap                     mNameMap;
    191199    Memoizer                    mMemoizer;
     200    RE_Syntax                   mReSyntax;
    192201};
    193202
  • icGREP/icgrep-devel/icgrep/re/re_parser_bre.cpp

    r5181 r5206  
    3333    }
    3434
    35     RE * RE_Parser_BRE::parse_alt() {
     35    RE * RE_Parser_BRE::parse_alt_with_intersect(RE *reToBeIntersected) {
    3636        std::vector<RE *> alt;
    3737        for (;;) {
    38             alt.push_back(parse_seq());
     38            alt.push_back(parse_seq_with_intersect(reToBeIntersected));
    3939
    4040            if (!isEscapedCharAhead('|')) {
     
    188188    }
    189189
    190     inline bool RE_Parser_BRE::isCharAhead(char c) {
    191         if (mCursor.remaining() < 2) {
    192             return false;
    193         }
    194         auto nextCursor = mCursor.pos() + 1;
    195         return *nextCursor == c;
    196     }
    197 
    198190    inline std::pair<int, int> RE_Parser_BRE::parse_range_bound() {
    199191        int lower_bound = 0, upper_bound = 0;
     
    297289        }
    298290        if (*mCursor == '=') {
     291            // We have a property-name = value expression
    299292            const auto prop_end = mCursor.pos();
    300293            mCursor++;
    301             const auto val_start = mCursor.pos();
    302             while (mCursor.more()) {
    303                 if (isEscapedCharAhead('}') || *mCursor == ':') {
    304                     break;
    305                 }
    306                 ++mCursor;
    307             }
    308             // We have a property-name = value expression
    309             return createName(canonicalize(start, prop_end), canonicalize(val_start, mCursor.pos()));
     294            auto val_start = mCursor.pos();
     295            if (*val_start != '\\' || !isCharAhead('/')) {
     296                // property-value is normal string
     297                while (mCursor.more()) {
     298                    if (isEscapedCharAhead('}') || *mCursor == ':') {
     299                        break;
     300                    }
     301                    ++mCursor;
     302                }
     303                return createName(canonicalize(start, prop_end), canonicalize(val_start, mCursor.pos()));
     304            } else {
     305                // property-value is another regex
     306                ++mCursor;
     307                auto previous = val_start;
     308                auto current = (++mCursor).pos();
     309                val_start = current;
     310
     311                while (true) {
     312                    if (*current == '/' && *previous == '\\') {
     313                        break;
     314                    }
     315
     316                    if (!mCursor.more()) {
     317                        ParseFailure("Malformed property expression");
     318                    }
     319
     320                    previous = current;
     321                    current = (++mCursor).pos();
     322                }
     323                ++mCursor;
     324                return parseRegexPropertyValue(canonicalize(start, prop_end), canonicalize(val_start, previous));
     325            }
    310326        }
    311327        return createName(canonicalize(start, mCursor.pos()));
  • icGREP/icgrep-devel/icgrep/re/re_parser_bre.h

    r5180 r5206  
    1313    class RE_Parser_BRE : public RE_Parser  {
    1414    public:
    15         RE_Parser_BRE(const std::string & regular_expression) : RE_Parser(regular_expression)  {
    16 
     15        RE_Parser_BRE(const std::string & regular_expression) : RE_Parser(regular_expression) {
     16            mReSyntax = RE_Syntax::BRE;
    1717        }
    1818
     
    2020        virtual bool isSetEscapeChar(char c) override;
    2121        virtual bool isUnsupportChartsetOperator(char c) override;
    22         virtual RE * parse_alt() override;
     22        virtual RE * parse_alt_with_intersect(RE* reToBeIntersected) override;
    2323        virtual RE * parse_next_item() override ;
    2424        virtual RE * parse_escaped() override;
     
    3232    private:
    3333        bool isEscapedCharAhead(char c);
    34         bool isCharAhead(char c);
     34
    3535    };
    3636}
  • icGREP/icgrep-devel/icgrep/re/re_parser_ere.h

    r5180 r5206  
    1212    class RE_Parser_ERE : public RE_Parser  {
    1313    public:
    14         RE_Parser_ERE(const std::string & regular_expression) : RE_Parser(regular_expression)  {
    15 
     14        RE_Parser_ERE(const std::string & regular_expression) : RE_Parser(regular_expression) {
     15            mReSyntax = RE_Syntax::ERE;
    1616        }
    1717
  • icGREP/icgrep-devel/icgrep/re/re_parser_pcre.h

    r5180 r5206  
    1414        RE_Parser_PCRE(const std::string & regular_expression) : RE_Parser(regular_expression) {
    1515            fSupportNonCaptureGroup = true;
     16            mReSyntax = RE_Syntax ::PCRE;
    1617        }
    1718    protected:
Note: See TracChangeset for help on using the changeset viewer.